Mercurial > games > semicongine
changeset 777:754835bf175e
add: changing rendering system, not finished yet, also upgrading to Nim 2
author | Sam <sam@basx.dev> |
---|---|
date | Mon, 07 Aug 2023 00:23:00 +0700 |
parents | 002d9c576756 |
children | dfc5978a3168 |
files | config.nims examples/E01_hello_triangle.nim examples/E02_squares.nim examples/E03_hello_cube.nim examples/E04_input.nim examples/E10_pong.nim src/semicongine/audio.nim src/semicongine/core/buildconfig.nim src/semicongine/engine.nim src/semicongine/mesh.nim src/semicongine/renderer.nim src/semicongine/resources/mesh.nim src/semicongine/scene.nim src/semicongine/vulkan/descriptor.nim src/semicongine/vulkan/shader.nim tests/test_audio.nim tests/test_font.nim tests/test_materials.nim tests/test_mesh.nim tests/test_vulkan_wrapper.nim |
diffstat | 20 files changed, 192 insertions(+), 158 deletions(-) [+] |
line wrap: on
line diff
--- a/config.nims Sun Jul 23 19:53:10 2023 +0700 +++ b/config.nims Mon Aug 07 00:23:00 2023 +0700 @@ -37,7 +37,7 @@ rmDir(outdir) mkDir(outdir) let resourcedir = joinPath(projectDir(), RESOURCEROOT) - if existsDir(resourcedir): + if dirExists(resourcedir): let outdir_resources = joinPath(outdir, RESOURCEROOT) if BUNDLETYPE == "dir": cpDir(resourcedir, outdir_resources) @@ -66,6 +66,11 @@ if file.endsWith(".nim"): exec(&"nim build -d:release {file}") +task test_all, "Run all test programs": + for file in listFiles("tests"): + if file.endsWith(".nim"): + exec(&"nim build --run {file}") + task clean, "remove all build files": exec(&"rm -rf {BUILDBASE}")
--- a/examples/E01_hello_triangle.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/examples/E01_hello_triangle.nim Mon Aug 07 00:23:00 2023 +0700 @@ -2,26 +2,21 @@ const - vertexInput = @[ + inputs = @[ attr[Vec3f]("position"), attr[Vec4f]("color"), ] - vertexOutput = @[attr[Vec4f]("outcolor")] - fragOutput = @[attr[Vec4f]("color")] - vertexCode = compileGlslShader( - stage=VK_SHADER_STAGE_VERTEX_BIT, - inputs=vertexInput, - outputs=vertexOutput, - main=""" + intermediate = @[attr[Vec4f]("outcolor")] + outputs = @[attr[Vec4f]("color")] + (vertexCode, fragmentCode) = compileVertexFragmentShaderSet( + inputs=inputs, + intermediate=intermediate, + outputs=outputs, + vertexCode=""" gl_Position = vec4(position, 1.0); outcolor = color; - """ - ) - fragmentCode = compileGlslShader( - stage=VK_SHADER_STAGE_FRAGMENT_BIT, - inputs=vertexOutput, - outputs=fragOutput, - main="color = outcolor;" + """, + fragmentCode="color = outcolor;", ) var @@ -36,7 +31,7 @@ renderPass = myengine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode) myengine.setRenderer(renderPass) -myengine.addScene(triangle, vertexInput, @[], transformAttribute="") +myengine.addScene(triangle, inputs, @[], transformAttribute="") while myengine.updateInputs() == Running and not myengine.keyWasPressed(Escape): myengine.renderScene(triangle)
--- a/examples/E02_squares.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/examples/E02_squares.nim Mon Aug 07 00:23:00 2023 +0700 @@ -42,34 +42,28 @@ const - vertexInput = @[ + inputs = @[ attr[Vec3f]("position"), attr[Vec4f]("color", memoryPerformanceHint=PreferFastWrite), attr[uint32]("index"), ] - vertexOutput = @[attr[Vec4f]("outcolor")] + intermediate = @[attr[Vec4f]("outcolor")] uniforms = @[attr[float32]("time")] - fragOutput = @[attr[Vec4f]("color")] - vertexCode = compileGlslShader( - stage=VK_SHADER_STAGE_VERTEX_BIT, - inputs=vertexInput, + outputs = @[attr[Vec4f]("color")] + (vertexCode, fragmentCode) = compileVertexFragmentShaderSet( + inputs=inputs, + intermediate=intermediate, + outputs=outputs, uniforms=uniforms, - outputs=vertexOutput, - main=""" + vertexCode=""" float pos_weight = index / 100.0; // add some gamma correction? float t = sin(Uniforms.time * 0.5) * 0.5 + 0.5; float v = min(1, max(0, pow(pos_weight - t, 2))); v = pow(1 - v, 3000); outcolor = vec4(color.r, color.g, v * 0.5, 1); gl_Position = vec4(position, 1.0); -""" - ) - fragmentCode = compileGlslShader( - stage=VK_SHADER_STAGE_FRAGMENT_BIT, - inputs=vertexOutput, - uniforms=uniforms, - outputs=fragOutput, - main="color = outcolor;" +""", + fragmentCode="color = outcolor;", ) var squaremesh = newMesh( positions=vertices, @@ -82,7 +76,7 @@ myengine.setRenderer(myengine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode)) var scene = newScene("scene", newEntity("scene", [], newEntity("squares", {"mesh": Component(squaremesh)}))) - myengine.addScene(scene, vertexInput, @[], transformAttribute="") + myengine.addScene(scene, inputs, @[], transformAttribute="") scene.addShaderGlobal("time", 0.0'f32) while myengine.updateInputs() == Running and not myengine.keyWasPressed(Escape): setShaderGlobal(scene, "time", getShaderGlobal[float32](scene, "time") + 0.0005'f)
--- a/examples/E03_hello_cube.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/examples/E03_hello_cube.nim Mon Aug 07 00:23:00 2023 +0700 @@ -52,37 +52,31 @@ var myengine = initEngine("Hello cube") const - vertexInput = @[ + inputs = @[ attr[Vec3f]("position"), attr[Vec4f]("color", memoryPerformanceHint=PreferFastWrite), ] - vertexOutput = @[attr[Vec4f]("outcolor")] + intermediate = @[attr[Vec4f]("outcolor")] uniforms = @[ attr[Mat4]("projection"), attr[Mat4]("view"), attr[Mat4]("model"), ] fragOutput = @[attr[Vec4f]("color")] - vertexCode = compileGlslShader( - stage=VK_SHADER_STAGE_VERTEX_BIT, - inputs=vertexInput, + (vertexCode, fragmentCode) = compileVertexFragmentShaderSet( + inputs=inputs, + intermediate=intermediate, + outputs=fragOutput, uniforms=uniforms, - outputs=vertexOutput, - main="""outcolor = color; gl_Position = (Uniforms.projection * Uniforms.view * Uniforms.model) * vec4(position, 1);""" - ) - fragmentCode = compileGlslShader( - stage=VK_SHADER_STAGE_FRAGMENT_BIT, - inputs=vertexOutput, - uniforms=uniforms, - outputs=fragOutput, - main="color = outcolor;" + vertexCode="""outcolor = color; gl_Position = (Uniforms.projection * Uniforms.view * Uniforms.model) * vec4(position, 1);""", + fragmentCode="color = outcolor;", ) myengine.setRenderer(myengine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode)) var cube = newScene("scene", newEntity("cube", {"mesh": Component(newMesh(positions=cube_pos, indices=tris, colors=cube_color))})) cube.addShaderGlobal("projection", Unit4f32) cube.addShaderGlobal("view", Unit4f32) cube.addShaderGlobal("model", Unit4f32) - myengine.addScene(cube, vertexInput, @[], transformAttribute="") + myengine.addScene(cube, inputs, @[], transformAttribute="") var t: float32 = cpuTime() while myengine.updateInputs() == Running and not myengine.keyWasPressed(Escape):
--- a/examples/E04_input.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/examples/E04_input.nim Mon Aug 07 00:23:00 2023 +0700 @@ -147,32 +147,26 @@ # shaders const - vertexInput = @[ + inputs = @[ attr[Vec3f]("position"), attr[Vec4f]("color", memoryPerformanceHint=PreferFastWrite), attr[Mat4]("transform", memoryPerformanceHint=PreferFastWrite, perInstance=true), ] - vertexOutput = @[attr[Vec4f]("outcolor")] + intermediate = @[attr[Vec4f]("outcolor")] uniforms = @[attr[Mat4]("projection")] - fragOutput = @[attr[Vec4f]("color")] - vertexCode = compileGlslShader( - stage=VK_SHADER_STAGE_VERTEX_BIT, - inputs=vertexInput, + outputs = @[attr[Vec4f]("color")] + (vertexCode, fragmentCode) = compileVertexFragmentShaderSet( + inputs=inputs, + intermediate=intermediate, + outputs=outputs, uniforms=uniforms, - outputs=vertexOutput, - main="""outcolor = color; gl_Position = vec4(position, 1) * (transform * Uniforms.projection);""" - ) - fragmentCode = compileGlslShader( - stage=VK_SHADER_STAGE_FRAGMENT_BIT, - inputs=vertexOutput, - uniforms=uniforms, - outputs=fragOutput, - main="color = outcolor;" + vertexCode="""outcolor = color; gl_Position = vec4(position, 1) * (transform * Uniforms.projection);""", + fragmentCode="color = outcolor;", ) # set up rendering myengine.setRenderer(myengine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode, clearColor=newVec4f(0, 0, 0.5))) - myengine.addScene(scene, vertexInput, @[], transformAttribute="transform") + myengine.addScene(scene, inputs, @[], transformAttribute="transform") scene.addShaderGlobal("projection", Unit4f32) # mainloop
--- a/examples/E10_pong.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/examples/E10_pong.nim Mon Aug 07 00:23:00 2023 +0700 @@ -31,32 +31,26 @@ level.root.add ball const - vertexInput = @[ + inputs = @[ attr[Vec3f]("position"), attr[Vec4f]("color", memoryPerformanceHint=PreferFastWrite), attr[Mat4]("transform", memoryPerformanceHint=PreferFastWrite, perInstance=true), ] - vertexOutput = @[attr[Vec4f]("outcolor")] + intermediate = @[attr[Vec4f]("outcolor")] uniforms = @[attr[Mat4]("projection")] - fragOutput = @[attr[Vec4f]("color")] - vertexCode = compileGlslShader( - stage=VK_SHADER_STAGE_VERTEX_BIT, - inputs=vertexInput, + outputs = @[attr[Vec4f]("color")] + (vertexCode, fragmentCode) = compileVertexFragmentShaderSet( + inputs=inputs, + intermediate=intermediate, + outputs=outputs, uniforms=uniforms, - outputs=vertexOutput, - main="""outcolor = color; gl_Position = vec4(position, 1) * (transform * Uniforms.projection);""" - ) - fragmentCode = compileGlslShader( - stage=VK_SHADER_STAGE_FRAGMENT_BIT, - inputs=vertexOutput, - uniforms=uniforms, - outputs=fragOutput, - main="color = outcolor;" + vertexCode="""outcolor = color; gl_Position = vec4(position, 1) * (transform * Uniforms.projection);""", + fragmentCode="color = outcolor;", ) # set up rendering myengine.setRenderer(myengine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode, clearColor=backgroundColor)) - myengine.addScene(level, vertexInput, @[], transformAttribute="transform") + myengine.addScene(level, inputs, @[], transformAttribute="transform") level.addShaderGlobal("projection", Unit4f32) var
--- a/src/semicongine/audio.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/src/semicongine/audio.nim Mon Aug 07 00:23:00 2023 +0700 @@ -15,7 +15,6 @@ const NBUFFERS = 4 const BUFFERSAMPLECOUNT = 2048 -const SOUND_SCALE = 4 # SOUND_SCALE is logarithm-scale type Playback = object
--- a/src/semicongine/core/buildconfig.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/src/semicongine/core/buildconfig.nim Mon Aug 07 00:23:00 2023 +0700 @@ -1,6 +1,5 @@ import std/parsecfg import std/streams -import std/compilesettings import std/strutils import std/logging import std/os @@ -15,7 +14,6 @@ # checks required build options: static: - assert querySetting(gc) == "orc", ENGINENAME & " requires --mm=orc" assert compileOption("threads"), ENGINENAME & " requires --threads=on" if defined(release):
--- a/src/semicongine/engine.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/src/semicongine/engine.nim Mon Aug 07 00:23:00 2023 +0700 @@ -1,4 +1,5 @@ import std/sequtils +import std/tables import std/options import std/logging import std/os @@ -10,6 +11,7 @@ import ./vulkan/device import ./vulkan/physicaldevice import ./vulkan/renderpass +import ./vulkan/shader import ./scene import ./renderer @@ -108,6 +110,17 @@ proc addScene*(engine: var Engine, scene: Scene, vertexInput: seq[ShaderAttribute], samplers: seq[ShaderAttribute], transformAttribute="transform", materialIndexAttribute="materialIndex") = assert transformAttribute == "" or transformAttribute in map(vertexInput, proc(a: ShaderAttribute): string = a.name) + assert materialIndexAttribute == "" or materialIndexAttribute in map(vertexInput, proc(a: ShaderAttribute): string = a.name) + assert engine.renderer.isSome + engine.renderer.get.setupDrawableBuffers(scene, vertexInput, samplers, transformAttribute=transformAttribute, materialIndexAttribute=materialIndexAttribute) + +proc addScene*(engine: var Engine, scene: Scene, materialShaders: Table[string, ShaderConfiguration], transformAttribute="transform", materialIndexAttribute="materialIndex") = + if transformAttribute != "": + for shader in materialShaders.values: + assert transformAttribute in map(shader.inputs, proc(a: ShaderAttribute): string = a.name) + if materialIndexAttribute != "": + for shader in materialShaders.values: + assert materialIndexAttribute in map(shader.inputs, proc(a: ShaderAttribute): string = a.name) assert engine.renderer.isSome engine.renderer.get.setupDrawableBuffers(scene, vertexInput, samplers, transformAttribute=transformAttribute, materialIndexAttribute=materialIndexAttribute)
--- a/src/semicongine/mesh.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/src/semicongine/mesh.nim Mon Aug 07 00:23:00 2023 +0700 @@ -8,7 +8,6 @@ import ./core import ./scene import ./collision -import ./material type MeshIndexType* = enum @@ -132,10 +131,10 @@ func indexDataSize*(mesh: Mesh): uint32 = case mesh.indexType - of None: 0 - of Tiny: mesh.tinyIndices.len * sizeof(get(genericParams(typeof(mesh.tinyIndices)), 0)) - of Small: mesh.smallIndices.len * sizeof(get(genericParams(typeof(mesh.smallIndices)), 0)) - of Big: mesh.bigIndices.len * sizeof(get(genericParams(typeof(mesh.bigIndices)), 0)) + of None: 0'u32 + of Tiny: uint32(mesh.tinyIndices.len * sizeof(get(genericParams(typeof(mesh.tinyIndices)), 0))) + of Small: uint32(mesh.smallIndices.len * sizeof(get(genericParams(typeof(mesh.smallIndices)), 0))) + of Big: uint32(mesh.bigIndices.len * sizeof(get(genericParams(typeof(mesh.bigIndices)), 0))) func rawData[T: seq](value: var T): (pointer, uint32) = (pointer(addr(value[0])), uint32(sizeof(get(genericParams(typeof(value)), 0)) * value.len))
--- a/src/semicongine/renderer.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/src/semicongine/renderer.nim Mon Aug 07 00:23:00 2023 +0700 @@ -92,6 +92,7 @@ mesh.initData(inputAttr) assert mesh.dataType(inputAttr.name) == inputAttr.thetype, &"mesh attribute {inputAttr.name} has type {mesh.dataType(inputAttr.name)} but shader expects {inputAttr.thetype}" if scenedata.materialIndexAttribute != "" and inputAttr.name == scenedata.materialIndexAttribute: + assert mesh.materials.len > 0, "Missing material specification for mesh. Either set the 'materials' attribute or pass the argument 'materialIndexAttribute=\"\"' when calling 'addScene'" assert mesh.materials.len == getMeshData[uint16](mesh, scenedata.materialIndexAttribute)[].len for i, material in enumerate(mesh.materials): let matIndex = materialIndex(scene, material) @@ -135,7 +136,7 @@ inc bindingNumber # setup one buffer per attribute-location-type for mesh in allMeshes: - # align size to VERTEX_ATTRIB_ALIGNMENT bytes (the important thing is the correct alignment of the offsets, bu + # align size to VERTEX_ATTRIB_ALIGNMENT bytes (the important thing is the correct alignment of the offsets, but # we need to expand the buffer size as well, therefore considering alignment already here as well if perLocationSizes[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT != 0: perLocationSizes[attribute.memoryPerformanceHint] += VERTEX_ATTRIB_ALIGNMENT - (perLocationSizes[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT)
--- a/src/semicongine/resources/mesh.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/src/semicongine/resources/mesh.nim Mon Aug 07 00:23:00 2023 +0700 @@ -103,7 +103,7 @@ raise newException(Exception, "Unsupported feature: byteStride in buffer view") copyMem(dstPointer, addr mainBuffer[bufferOffset], result.len) -proc getAccessorData(root: JsonNode, accessor: JsonNode, mainBuffer: var seq[uint8]): DataList = +proc getAccessorData(root: JsonNode, accessor: JsonNode, mainBuffer: seq[uint8]): DataList = result = newDataList(thetype=accessor.getGPUType()) result.initData(uint32(accessor["count"].getInt())) @@ -127,7 +127,7 @@ else: copyMem(dstPointer, addr mainBuffer[bufferOffset], length) -proc addPrimitive(mesh: var Mesh, root: JsonNode, primitiveNode: JsonNode, mainBuffer: var seq[uint8]) = +proc addPrimitive(mesh: var Mesh, root: JsonNode, primitiveNode: JsonNode, mainBuffer: seq[uint8]) = if primitiveNode.hasKey("mode") and primitiveNode["mode"].getInt() != 4: raise newException(Exception, "Currently only TRIANGLE mode is supported for geometry mode") @@ -163,7 +163,8 @@ else: raise newException(Exception, &"Unsupported index data type: {data.thetype}") -proc loadMesh(root: JsonNode, meshNode: JsonNode, mainBuffer: var seq[uint8], materials: seq[Material]): Mesh = +# TODO: use one mesh per primitive?? right now we are merging primitives... check addPrimitive below +proc loadMesh(root: JsonNode, meshNode: JsonNode, mainBuffer: seq[uint8], materials: seq[string]): Mesh = result = Mesh(instanceCount: 1, instanceTransforms: newSeqWith(1, Unit4F32)) # check if and how we use indexes @@ -187,7 +188,6 @@ # prepare mesh attributes for attribute, accessor in meshNode["primitives"][0]["attributes"].pairs: result.setMeshData(attribute.toLowerAscii, newDataList(thetype=root["accessors"][accessor.getInt()].getGPUType())) - result.setMeshData("material", newDataList(thetype=getDataType[uint8]())) # add all mesh data for primitive in meshNode["primitives"]: @@ -195,7 +195,7 @@ setInstanceData(result, "transform", newSeqWith(int(result.instanceCount), Unit4F32)) -proc loadNode(root: JsonNode, node: JsonNode, mainBuffer: var seq[uint8], materials: seq[Material]): Entity = +proc loadNode(root: JsonNode, node: JsonNode, mainBuffer: var seq[uint8], materials: seq[string]): Entity = var name = "<Unknown>" if node.hasKey("name"): name = node["name"].getStr() @@ -241,7 +241,7 @@ if node.hasKey("mesh"): result["mesh"] = loadMesh(root, root["meshes"][node["mesh"].getInt()], mainBuffer, materials) -proc loadScene(root: JsonNode, scenenode: JsonNode, mainBuffer: var seq[uint8], materials: seq[Material]): Scene = +proc loadScene(root: JsonNode, scenenode: JsonNode, mainBuffer: var seq[uint8], materials: seq[string]): Scene = var rootEntity = newEntity("<root>") for nodeId in scenenode["nodes"]: var node = loadNode(root, root["nodes"][nodeId.getInt()], mainBuffer, materials) @@ -369,10 +369,12 @@ debug data.structuredContent.pretty - for scene in data.structuredContent["scenes"]: - var materials: seq[Material] + for scenedata in data.structuredContent["scenes"]: + var materials: seq[string] + var scene = data.structuredContent.loadScene(scenedata, data.binaryBufferData, materials) for i, materialNode in enumerate(data.structuredContent["materials"]): - materials.add loadMaterial(data.structuredContent, materialNode, data.binaryBufferData, i) - var scene = data.structuredContent.loadScene(scene, data.binaryBufferData, materials) + let material = loadMaterial(data.structuredContent, materialNode, data.binaryBufferData, i) + materials.add material.name + scene.addMaterial material result.add scene
--- a/src/semicongine/scene.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/src/semicongine/scene.nim Mon Aug 07 00:23:00 2023 +0700 @@ -1,6 +1,5 @@ import std/strformat import std/sequtils -import std/algorithm import std/strutils import std/tables import std/hashes @@ -17,13 +16,6 @@ shaderGlobals*: Table[string, DataList] materials: OrderedTable[string, Material] - #[ - Material* = object - name*: string - textures*: Table[string, Texture] - data*: Table[string, DataValue] - ]# - Component* = ref object of RootObj entity*: Entity @@ -173,7 +165,7 @@ for (name, comp) in components: result[name] = comp if result.name == "": - result.name = &"Entity[{$(cast[ByteAddress](result))}]" + result.name = &"Entity[{$(cast[uint](result))}]" result.internal_transform = Unit4 iterator allEntitiesOfType*[T: Entity](root: Entity): T =
--- a/src/semicongine/vulkan/descriptor.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/src/semicongine/vulkan/descriptor.nim Mon Aug 07 00:23:00 2023 +0700 @@ -151,7 +151,6 @@ descriptorCount: descriptor.count, pBufferInfo: addr bufferInfos[^1], ) - echo bufferInfos elif descriptor.thetype == ImageSampler: var imgInfo: seq[VkDescriptorImageInfo] for img_i in 0 ..< descriptor.count: @@ -173,5 +172,4 @@ pImageInfo: imgInfos[^1].toCPointer, ) inc i - echo descriptorSetWrites descriptorSet.layout.device.vk.vkUpdateDescriptorSets(uint32(descriptorSetWrites.len), descriptorSetWrites.toCPointer, 0, nil)
--- a/src/semicongine/vulkan/shader.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/src/semicongine/vulkan/shader.nim Mon Aug 07 00:23:00 2023 +0700 @@ -34,6 +34,15 @@ uniforms*: seq[ShaderAttribute] samplers*: seq[ShaderAttribute] outputs*: seq[ShaderAttribute] + ShaderConfiguration* = object + vertexBinary: seq[uint32] + fragmentBinary: seq[uint32] + entrypoint: string + inputs*: seq[ShaderAttribute] + intermediates*: seq[ShaderAttribute] + outputs*: seq[ShaderAttribute] + uniforms*: seq[ShaderAttribute] + samplers*: seq[ShaderAttribute] proc compileGlslToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] {.compileTime.} = @@ -97,8 +106,7 @@ main: string ): ShaderCode {.compileTime.} = - var code = @[&"#version {version}", "#extension GL_EXT_scalar_block_layout : require", ""] & - # var code = @[&"#version {version}", "layout(row_major) uniform;", ""] & + let code = @[&"#version {version}", "#extension GL_EXT_scalar_block_layout : require", ""] & (if inputs.len > 0: inputs.glslInput() & @[""] else: @[]) & (if uniforms.len > 0: uniforms.glslUniforms(binding=0) & @[""] else: @[]) & (if samplers.len > 0: samplers.glslSamplers(basebinding=if uniforms.len > 0: 1 else: 0) & @[""] else: @[]) & @@ -114,7 +122,28 @@ result.stage = stage result.binary = compileGlslToSPIRV(stage, code.join("\n"), entrypoint) -proc compileVertextShader*( +proc compileGlslCode*( + stage: VkShaderStageFlagBits, + inputs: seq[ShaderAttribute]= @[], + uniforms: seq[ShaderAttribute]= @[], + samplers: seq[ShaderAttribute]= @[], + outputs: seq[ShaderAttribute]= @[], + version=DEFAULT_SHADER_VERSION , + entrypoint=DEFAULT_SHADER_ENTRYPOINT , + main: string +): seq[uint32] {.compileTime.} = + + let code = @[&"#version {version}", "#extension GL_EXT_scalar_block_layout : require", ""] & + (if inputs.len > 0: inputs.glslInput() & @[""] else: @[]) & + (if uniforms.len > 0: uniforms.glslUniforms(binding=0) & @[""] else: @[]) & + (if samplers.len > 0: samplers.glslSamplers(basebinding=if uniforms.len > 0: 1 else: 0) & @[""] else: @[]) & + (if outputs.len > 0: outputs.glslOutput() & @[""] else: @[]) & + @[&"void {entrypoint}(){{"] & + main & + @[&"}}"] + compileGlslToSPIRV(stage, code.join("\n"), entrypoint) + +proc compileVertexShader*( inputs: seq[ShaderAttribute]= @[], uniforms: seq[ShaderAttribute]= @[], samplers: seq[ShaderAttribute]= @[], @@ -166,7 +195,7 @@ fragmentCode: string, ): (ShaderCode, ShaderCode) {.compileTime.} = - result[0] = compileVertextShader( + result[0] = compileVertexShader( inputs=inputs, outputs=intermediate, uniforms=uniforms, @@ -185,6 +214,42 @@ main=fragmentCode ) +proc createShaderConfiguration*( + inputs: seq[ShaderAttribute]= @[], + intermediates: seq[ShaderAttribute]= @[], + outputs: seq[ShaderAttribute]= @[], + uniforms: seq[ShaderAttribute]= @[], + samplers: seq[ShaderAttribute]= @[], + version=DEFAULT_SHADER_VERSION , + entrypoint=DEFAULT_SHADER_ENTRYPOINT , + vertexCode: string, + fragmentCode: string, +): ShaderConfiguration {.compileTime.} = + ShaderConfiguration( + vertexBinary: compileGlslCode( + stage=VK_SHADER_STAGE_VERTEX_BIT, + inputs=inputs, + outputs=intermediates, + uniforms=uniforms, + samplers=samplers, + main=vertexCode, + ), + fragmentBinary: compileGlslCode( + stage=VK_SHADER_STAGE_FRAGMENT_BIT, + inputs=inputs, + outputs=intermediates, + uniforms=uniforms, + samplers=samplers, + main=fragmentCode, + ), + entrypoint: entrypoint, + inputs: inputs, + intermediates: intermediates, + outputs: outputs, + uniforms: uniforms, + samplers: samplers, + ) + proc createShaderModule*( device: Device,
--- a/tests/test_audio.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/tests/test_audio.nim Mon Aug 07 00:23:00 2023 +0700 @@ -76,5 +76,5 @@ mixer[].stop() test2() mixer[].stop() - test3() - mixer[].stop() + # test3() + # mixer[].stop()
--- a/tests/test_font.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/tests/test_font.nim Mon Aug 07 00:23:00 2023 +0700 @@ -45,7 +45,7 @@ var engine = initEngine("Test fonts") engine.setRenderer(engine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode)) - engine.addScene(scene, vertexInput, samplers) + engine.addScene(scene, vertexInput, samplers, materialIndexAttribute="") scene.addShaderGlobal("perspective", Unit4F32) while engine.updateInputs() == Running and not engine.keyIsDown(Escape):
--- a/tests/test_materials.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/tests/test_materials.nim Mon Aug 07 00:23:00 2023 +0700 @@ -5,6 +5,7 @@ proc main() = var flag = rect() + flag.materials = @["material2"] var scene = newScene("main", root=newEntity("rect", {"mesh": Component(flag)})) let (RT, WT, PT) = (hexToColorAlpha("A51931").asPixel, hexToColorAlpha("F4F5F8").asPixel, hexToColorAlpha("2D2A4A").asPixel) let @@ -24,12 +25,12 @@ sampler.magnification = VK_FILTER_NEAREST sampler.minification = VK_FILTER_NEAREST scene.addMaterial(Material(name:"material1", textures: { - "swissflag": Texture(image: swiss, sampler: sampler), - "thaiflag": Texture(image: thai, sampler: sampler), + "tex1": Texture(image: swiss, sampler: sampler), + "tex2": Texture(image: thai, sampler: sampler), }.toTable)) scene.addMaterial(Material(name:"material2", textures: { - "swissflag": Texture(image: thai, sampler: sampler), - "thaiflag": Texture(image: swiss, sampler: sampler), + "tex1": Texture(image: thai, sampler: sampler), + "tex2": Texture(image: swiss, sampler: sampler), }.toTable)) scene.addShaderGlobalArray("test2", @[0'f32, 0'f32]) @@ -38,36 +39,33 @@ const vertexInput = @[ attr[Vec3f]("position", memoryPerformanceHint=PreferFastRead), + attr[uint16]("materialIndex", memoryPerformanceHint=PreferFastRead, perInstance=true), attr[Vec2f]("uv", memoryPerformanceHint=PreferFastRead), ] - vertexOutput = @[attr[Vec2f]("uvout")] + vertexOutput = @[attr[Vec2f]("uvout"), attr[uint16]("materialIndexOut", noInterpolation=true)] uniforms = @[attr[float32]("test2", arrayCount=2)] samplers = @[ - attr[Sampler2DType]("swissflag", arrayCount=2), - attr[Sampler2DType]("thaiflag", arrayCount=2), + attr[Sampler2DType]("tex1", arrayCount=2), + attr[Sampler2DType]("tex2", arrayCount=2), ] fragOutput = @[attr[Vec4f]("color")] - vertexCode = compileGlslShader( - stage=VK_SHADER_STAGE_VERTEX_BIT, + (vertexCode, fragmentCode) = compileVertexFragmentShaderSet( inputs=vertexInput, - uniforms=uniforms, + intermediate=vertexOutput, + outputs=fragOutput, samplers=samplers, - outputs=vertexOutput, - main="""gl_Position = vec4(position.x, position.y + sin(Uniforms.test2[1]) / Uniforms.test2[1] * 0.5, position.z, 1.0); uvout = uv;""" - ) - fragmentCode = compileGlslShader( - stage=VK_SHADER_STAGE_FRAGMENT_BIT, - inputs=vertexOutput, uniforms=uniforms, - samplers=samplers, - outputs=fragOutput, - main=""" -float d = sin(Uniforms.test2[0]) * 0.5 + 0.5; -color = texture(swissflag[1], uvout) * (1 - d) + texture(thaiflag[1], uvout) * d; -""" + vertexCode=""" + gl_Position = vec4(position.x, position.y + sin(Uniforms.test2[1]) / Uniforms.test2[1] * 0.5, position.z, 1.0); + uvout = uv; + materialIndexOut = materialIndex;""", + fragmentCode=""" + float d = sin(Uniforms.test2[0]) * 0.5 + 0.5; + color = texture(tex1[materialIndexOut], uvout) * (1 - d) + texture(tex2[materialIndexOut], uvout) * d; + """, ) engine.setRenderer(engine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode)) - engine.addScene(scene, vertexInput, samplers, transformAttribute="", materialIndexAttribute="") + engine.addScene(scene, vertexInput, samplers, transformAttribute="") var t = cpuTime() while engine.updateInputs() == Running and not engine.keyIsDown(Escape): var d = float32(cpuTime() - t)
--- a/tests/test_mesh.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/tests/test_mesh.nim Mon Aug 07 00:23:00 2023 +0700 @@ -5,7 +5,7 @@ var ent2 = newEntity("hehe", [], ent1) var myScene = newScene("hi", ent2) myScene.root.transform = translate3d(0.2'f32, 0'f32, 0'f32) - myScene.root.children[0].transform = translate3d(0'f32, 0.2'f32, 0'f32) + myScene.root[0].transform = translate3d(0'f32, 0.2'f32, 0'f32) var scenes = [ # loadScene("default_cube.glb", "1"), # loadScene("default_cube1.glb", "3"), @@ -55,7 +55,7 @@ ) engine.setRenderer(engine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode, clearColor=newVec4f(0, 0, 0, 1))) for scene in scenes.mitems: - engine.addScene(scene, vertexInput, samplers, transformAttribute="transform") + engine.addScene(scene, vertexInput, samplers, transformAttribute="transform", materialIndexAttribute="") scene.addShaderGlobal("projection", Unit4) scene.addShaderGlobal("view", Unit4) var
--- a/tests/test_vulkan_wrapper.nim Sun Jul 23 19:53:10 2023 +0700 +++ b/tests/test_vulkan_wrapper.nim Mon Aug 07 00:23:00 2023 +0700 @@ -90,25 +90,18 @@ attr[Vec4f]("color", memoryPerformanceHint=PreferFastWrite), attr[Vec3f]("translate", perInstance=true) ] - vertexOutput = @[attr[Vec4f]("outcolor")] - uniforms = @[attr[float32]("time")] - samplers = @[attr[Sampler2DType]("my_little_texture")] + intermediate = @[attr[Vec4f]("outcolor")] fragOutput = @[attr[Vec4f]("color")] - vertexCode = compileGlslShader( - stage=VK_SHADER_STAGE_VERTEX_BIT, + samplers = @[attr[Sampler2DType]("my_little_texture")] + uniforms = @[attr[float32]("time")] + (vertexCode, fragmentCode) = compileVertexFragmentShaderSet( inputs=vertexInput, - uniforms=uniforms, + intermediate=intermediate, + outputs=fragOutput, samplers=samplers, - outputs=vertexOutput, - main="""gl_Position = vec4(position + translate, 1.0); outcolor = color;""" - ) - fragmentCode = compileGlslShader( - stage=VK_SHADER_STAGE_FRAGMENT_BIT, - inputs=vertexOutput, uniforms=uniforms, - samplers=samplers, - outputs=fragOutput, - main="color = texture(my_little_texture, outcolor.xy) * 0.5 + outcolor * 0.5;" + vertexCode="""gl_Position = vec4(position + translate, 1.0); outcolor = color;""", + fragmentCode="color = texture(my_little_texture, outcolor.xy) * 0.5 + outcolor * 0.5;", ) var renderPass = engine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode) engine.setRenderer(renderPass)