Mercurial > games > semicongine
changeset 870:b975eab2b694
did: improve dynamic array, mesh and material APIs a ton, changes in material attributes are now detected and will trigger uniform-updates
author | Sam <sam@basx.dev> |
---|---|
date | Sun, 07 Jan 2024 00:56:44 +0700 |
parents | 65afec4cb6c6 |
children | 1f1e959a5fa3 |
files | semicongine/core/dynamic_arrays.nim semicongine/material.nim semicongine/mesh.nim semicongine/renderer.nim semicongine/resources/mesh.nim semicongine/scene.nim |
diffstat | 6 files changed, 187 insertions(+), 207 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/core/dynamic_arrays.nim Thu Jan 04 21:13:11 2024 +0700 +++ b/semicongine/core/dynamic_arrays.nim Sun Jan 07 00:56:44 2024 +0700 @@ -1,4 +1,5 @@ import std/hashes +import std/tables import std/strformat import ./gpu_types @@ -200,7 +201,7 @@ of TextureType: discard -proc setValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = +proc setValues[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = value.setLen(data.len) when T is float32: value.float32[] = data elif T is float64: value.float64[] = data @@ -253,6 +254,59 @@ elif T is Texture: value.texture[] = data else: {. error: "Virtual datatype has no values" .} +proc setValue[T: GPUType|int|uint|float](value: var DataList, i: int, data: T) = + assert i < value.len + when T is float32: value.float32[i] = data + elif T is float64: value.float64[i] = data + elif T is int8: value.int8[i] = data + elif T is int16: value.int16[i] = data + elif T is int32: value.int32[i] = data + elif T is int64: value.int64[i] = data + elif T is uint8: value.uint8[i] = data + elif T is uint16: value.uint16[i] = data + elif T is uint32: value.uint32[i] = data + elif T is uint64: value.uint64[i] = data + elif T is int and sizeof(int) == sizeof(int32): value.int32[i] = data + elif T is int and sizeof(int) == sizeof(int64): value.int64[i] = data + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[i] = data + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[i] = data + elif T is float and sizeof(float) == sizeof(float32): value.float32[i] = data + elif T is float and sizeof(float) == sizeof(float64): value.float64[i] = data + elif T is TVec2[int32]: value.vec2i32[i] = data + elif T is TVec2[int64]: value.vec2i64[i] = data + elif T is TVec3[int32]: value.vec3i32[i] = data + elif T is TVec3[int64]: value.vec3i64[i] = data + elif T is TVec4[int32]: value.vec4i32[i] = data + elif T is TVec4[int64]: value.vec4i64[i] = data + elif T is TVec2[uint32]: value.vec2u32[i] = data + elif T is TVec2[uint64]: value.vec2u64[i] = data + elif T is TVec3[uint32]: value.vec3u32[i] = data + elif T is TVec3[uint64]: value.vec3u64[i] = data + elif T is TVec4[uint32]: value.vec4u32[i] = data + elif T is TVec4[uint64]: value.vec4u64[i] = data + elif T is TVec2[float32]: value.vec2f32[i] = data + elif T is TVec2[float64]: value.vec2f64[i] = data + elif T is TVec3[float32]: value.vec3f32[i] = data + elif T is TVec3[float64]: value.vec3f64[i] = data + elif T is TVec4[float32]: value.vec4f32[i] = data + elif T is TVec4[float64]: value.vec4f64[i] = data + elif T is TMat2[float32]: value.mat2f32[i] = data + elif T is TMat2[float64]: value.mat2f64[i] = data + elif T is TMat23[float32]: value.mat23f32[i] = data + elif T is TMat23[float64]: value.mat23f64[i] = data + elif T is TMat32[float32]: value.mat32f32[i] = data + elif T is TMat32[float64]: value.mat32f64[i] = data + elif T is TMat3[float32]: value.mat3f32[i] = data + elif T is TMat3[float64]: value.mat3f64[i] = data + elif T is TMat34[float32]: value.mat34f32[i] = data + elif T is TMat34[float64]: value.mat34f64[i] = data + elif T is TMat43[float32]: value.mat43f32[i] = data + elif T is TMat43[float64]: value.mat43f64[i] = data + elif T is TMat4[float32]: value.mat4f32[i] = data + elif T is TMat4[float64]: value.mat4f64[i] = data + elif T is Texture: value.texture[i] = data + else: {. error: "Virtual datatype has no values" .} + proc initDataList*(theType: DataType, len=0): DataList = result = DataList(theType: theType) case result.theType @@ -418,54 +472,65 @@ template `[]`*(list: DataList, i: int, t: typedesc): untyped = getValue[t](list, i) -func getRawData*(value: var DataList): (pointer, int) = +# since we use this often with tables, add this for an easy assignment +template `[]=`*[T](table: var Table[string, DataList], key: string, values: seq[T]) = + if key in table: + table[key].setValues(values) + else: + table[key] = initDataList(values) + +template `[]=`*[T](list: var DataList, values: seq[T]) = + list.setValues(values) +template `[]=`*[T](list: var DataList, i: int, value: T) = + list.setValue(i, value) + +func getPointer*(value: var DataList): pointer = if value.len == 0: - return (nil, 0) - result[1] = value.theType.size * value.len + result = nil case value.theType - of Float32: result[0] = value.float32[].toCPointer - of Float64: result[0] = value.float64[].toCPointer - of Int8: result[0] = value.int8[].toCPointer - of Int16: result[0] = value.int16[].toCPointer - of Int32: result[0] = value.int32[].toCPointer - of Int64: result[0] = value.int64[].toCPointer - of UInt8: result[0] = value.uint8[].toCPointer - of UInt16: result[0] = value.uint16[].toCPointer - of UInt32: result[0] = value.uint32[].toCPointer - of UInt64: result[0] = value.uint64[].toCPointer - of Vec2I32: result[0] = value.vec2i32[].toCPointer - of Vec2I64: result[0] = value.vec2i64[].toCPointer - of Vec3I32: result[0] = value.vec3i32[].toCPointer - of Vec3I64: result[0] = value.vec3i64[].toCPointer - of Vec4I32: result[0] = value.vec4i32[].toCPointer - of Vec4I64: result[0] = value.vec4i64[].toCPointer - of Vec2U32: result[0] = value.vec2u32[].toCPointer - of Vec2U64: result[0] = value.vec2u64[].toCPointer - of Vec3U32: result[0] = value.vec3u32[].toCPointer - of Vec3U64: result[0] = value.vec3u64[].toCPointer - of Vec4U32: result[0] = value.vec4u32[].toCPointer - of Vec4U64: result[0] = value.vec4u64[].toCPointer - of Vec2F32: result[0] = value.vec2f32[].toCPointer - of Vec2F64: result[0] = value.vec2f64[].toCPointer - of Vec3F32: result[0] = value.vec3f32[].toCPointer - of Vec3F64: result[0] = value.vec3f64[].toCPointer - of Vec4F32: result[0] = value.vec4f32[].toCPointer - of Vec4F64: result[0] = value.vec4f64[].toCPointer - of Mat2F32: result[0] = value.mat2f32[].toCPointer - of Mat2F64: result[0] = value.mat2f64[].toCPointer - of Mat23F32: result[0] = value.mat23f32[].toCPointer - of Mat23F64: result[0] = value.mat23f64[].toCPointer - of Mat32F32: result[0] = value.mat32f32[].toCPointer - of Mat32F64: result[0] = value.mat32f64[].toCPointer - of Mat3F32: result[0] = value.mat3f32[].toCPointer - of Mat3F64: result[0] = value.mat3f64[].toCPointer - of Mat34F32: result[0] = value.mat34f32[].toCPointer - of Mat34F64: result[0] = value.mat34f64[].toCPointer - of Mat43F32: result[0] = value.mat43f32[].toCPointer - of Mat43F64: result[0] = value.mat43f64[].toCPointer - of Mat4F32: result[0] = value.mat4f32[].toCPointer - of Mat4F64: result[0] = value.mat4f64[].toCPointer - of TextureType: result[0] = nil + of Float32: result = value.float32[].toCPointer + of Float64: result = value.float64[].toCPointer + of Int8: result = value.int8[].toCPointer + of Int16: result = value.int16[].toCPointer + of Int32: result = value.int32[].toCPointer + of Int64: result = value.int64[].toCPointer + of UInt8: result = value.uint8[].toCPointer + of UInt16: result = value.uint16[].toCPointer + of UInt32: result = value.uint32[].toCPointer + of UInt64: result = value.uint64[].toCPointer + of Vec2I32: result = value.vec2i32[].toCPointer + of Vec2I64: result = value.vec2i64[].toCPointer + of Vec3I32: result = value.vec3i32[].toCPointer + of Vec3I64: result = value.vec3i64[].toCPointer + of Vec4I32: result = value.vec4i32[].toCPointer + of Vec4I64: result = value.vec4i64[].toCPointer + of Vec2U32: result = value.vec2u32[].toCPointer + of Vec2U64: result = value.vec2u64[].toCPointer + of Vec3U32: result = value.vec3u32[].toCPointer + of Vec3U64: result = value.vec3u64[].toCPointer + of Vec4U32: result = value.vec4u32[].toCPointer + of Vec4U64: result = value.vec4u64[].toCPointer + of Vec2F32: result = value.vec2f32[].toCPointer + of Vec2F64: result = value.vec2f64[].toCPointer + of Vec3F32: result = value.vec3f32[].toCPointer + of Vec3F64: result = value.vec3f64[].toCPointer + of Vec4F32: result = value.vec4f32[].toCPointer + of Vec4F64: result = value.vec4f64[].toCPointer + of Mat2F32: result = value.mat2f32[].toCPointer + of Mat2F64: result = value.mat2f64[].toCPointer + of Mat23F32: result = value.mat23f32[].toCPointer + of Mat23F64: result = value.mat23f64[].toCPointer + of Mat32F32: result = value.mat32f32[].toCPointer + of Mat32F64: result = value.mat32f64[].toCPointer + of Mat3F32: result = value.mat3f32[].toCPointer + of Mat3F64: result = value.mat3f64[].toCPointer + of Mat34F32: result = value.mat34f32[].toCPointer + of Mat34F64: result = value.mat34f64[].toCPointer + of Mat43F32: result = value.mat43f32[].toCPointer + of Mat43F64: result = value.mat43f64[].toCPointer + of Mat4F32: result = value.mat4f32[].toCPointer + of Mat4F64: result = value.mat4f64[].toCPointer + of TextureType: nil proc appendValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = value.len += data.len @@ -568,112 +633,6 @@ of Mat4F64: value.mat4f64[].add data.mat4f64[] of TextureType: value.texture[].add data.texture[] -proc setValue*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = - value.len = data.len - when T is float32: value.float32[] = data - elif T is float64: value.float64[] = data - elif T is int8: value.int8[] = data - elif T is int16: value.int16[] = data - elif T is int32: value.int32[] = data - elif T is int64: value.int64[] = data - elif T is uint8: value.uint8[] = data - elif T is uint16: value.uint16[] = data - elif T is uint32: value.uint32[] = data - elif T is uint64: value.uint64[] = data - elif T is int and sizeof(int) == sizeof(int32): value.int32[] = data - elif T is int and sizeof(int) == sizeof(int64): value.int64[] = data - elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[] = data - elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[] = data - elif T is float and sizeof(float) == sizeof(float32): value.float32[] = data - elif T is float and sizeof(float) == sizeof(float64): value.float64[] = data - elif T is TVec2[int32]: value.vec2i32[] = data - elif T is TVec2[int64]: value.vec2i64[] = data - elif T is TVec3[int32]: value.vec3i32[] = data - elif T is TVec3[int64]: value.vec3i64[] = data - elif T is TVec4[int32]: value.vec4i32[] = data - elif T is TVec4[int64]: value.vec4i64[] = data - elif T is TVec2[uint32]: value.vec2u32[] = data - elif T is TVec2[uint64]: value.vec2u64[] = data - elif T is TVec3[uint32]: value.vec3u32[] = data - elif T is TVec3[uint64]: value.vec3u64[] = data - elif T is TVec4[uint32]: value.vec4u32[] = data - elif T is TVec4[uint64]: value.vec4u64[] = data - elif T is TVec2[float32]: value.vec2f32[] = data - elif T is TVec2[float64]: value.vec2f64[] = data - elif T is TVec3[float32]: value.vec3f32[] = data - elif T is TVec3[float64]: value.vec3f64[] = data - elif T is TVec4[float32]: value.vec4f32[] = data - elif T is TVec4[float64]: value.vec4f64[] = data - elif T is TMat2[float32]: value.mat2f32[] = data - elif T is TMat2[float64]: value.mat2f64[] = data - elif T is TMat23[float32]: value.mat23f32[] = data - elif T is TMat23[float64]: value.mat23f64[] = data - elif T is TMat32[float32]: value.mat32f32[] = data - elif T is TMat32[float64]: value.mat32f64[] = data - elif T is TMat3[float32]: value.mat3f32[] = data - elif T is TMat3[float64]: value.mat3f64[] = data - elif T is TMat34[float32]: value.mat34f32[] = data - elif T is TMat34[float64]: value.mat34f64[] = data - elif T is TMat43[float32]: value.mat43f32[] = data - elif T is TMat43[float64]: value.mat43f64[] = data - elif T is TMat4[float32]: value.mat4f32[] = data - elif T is TMat4[float64]: value.mat4f64[] = data - elif T is Texture: value.texture[] = data - else: {. error: "Virtual datatype has no values" .} - -proc setValue*[T: GPUType|int|uint|float](value: var DataList, i: int, data: T) = - assert i < value.len - when T is float32: value.float32[i] = data - elif T is float64: value.float64[i] = data - elif T is int8: value.int8[i] = data - elif T is int16: value.int16[i] = data - elif T is int32: value.int32[i] = data - elif T is int64: value.int64[i] = data - elif T is uint8: value.uint8[i] = data - elif T is uint16: value.uint16[i] = data - elif T is uint32: value.uint32[i] = data - elif T is uint64: value.uint64[i] = data - elif T is int and sizeof(int) == sizeof(int32): value.int32[i] = data - elif T is int and sizeof(int) == sizeof(int64): value.int64[i] = data - elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[i] = data - elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[i] = data - elif T is float and sizeof(float) == sizeof(float32): value.float32[i] = data - elif T is float and sizeof(float) == sizeof(float64): value.float64[i] = data - elif T is TVec2[int32]: value.vec2i32[i] = data - elif T is TVec2[int64]: value.vec2i64[i] = data - elif T is TVec3[int32]: value.vec3i32[i] = data - elif T is TVec3[int64]: value.vec3i64[i] = data - elif T is TVec4[int32]: value.vec4i32[i] = data - elif T is TVec4[int64]: value.vec4i64[i] = data - elif T is TVec2[uint32]: value.vec2u32[i] = data - elif T is TVec2[uint64]: value.vec2u64[i] = data - elif T is TVec3[uint32]: value.vec3u32[i] = data - elif T is TVec3[uint64]: value.vec3u64[i] = data - elif T is TVec4[uint32]: value.vec4u32[i] = data - elif T is TVec4[uint64]: value.vec4u64[i] = data - elif T is TVec2[float32]: value.vec2f32[i] = data - elif T is TVec2[float64]: value.vec2f64[i] = data - elif T is TVec3[float32]: value.vec3f32[i] = data - elif T is TVec3[float64]: value.vec3f64[i] = data - elif T is TVec4[float32]: value.vec4f32[i] = data - elif T is TVec4[float64]: value.vec4f64[i] = data - elif T is TMat2[float32]: value.mat2f32[i] = data - elif T is TMat2[float64]: value.mat2f64[i] = data - elif T is TMat23[float32]: value.mat23f32[i] = data - elif T is TMat23[float64]: value.mat23f64[i] = data - elif T is TMat32[float32]: value.mat32f32[i] = data - elif T is TMat32[float64]: value.mat32f64[i] = data - elif T is TMat3[float32]: value.mat3f32[i] = data - elif T is TMat3[float64]: value.mat3f64[i] = data - elif T is TMat34[float32]: value.mat34f32[i] = data - elif T is TMat34[float64]: value.mat34f64[i] = data - elif T is TMat43[float32]: value.mat43f32[i] = data - elif T is TMat43[float64]: value.mat43f64[i] = data - elif T is TMat4[float32]: value.mat4f32[i] = data - elif T is TMat4[float64]: value.mat4f64[i] = data - elif T is Texture: value.texture[i] = data - else: {. error: "Virtual datatype has no values" .} - proc appendFrom*(a: var DataList, i: int, b: DataList, j: int) = assert a.theType == b.theType case a.theType
--- a/semicongine/material.nim Thu Jan 04 21:13:11 2024 +0700 +++ b/semicongine/material.nim Sun Jan 07 00:56:44 2024 +0700 @@ -12,15 +12,16 @@ vertexAttributes*: Table[string, DataType] instanceAttributes*: Table[string, DataType] attributes*: Table[string, DataType] - MaterialData* = object + MaterialData* = ref object theType*: MaterialType name*: string attributes: Table[string, DataList] + dirtyAttributes: seq[string] -func hasMatchingAttribute*(materialType: MaterialType, attr: ShaderAttribute): bool = +proc hasMatchingAttribute*(materialType: MaterialType, attr: ShaderAttribute): bool = return materialType.attributes.contains(attr.name) and materialType.attributes[attr.name] == attr.theType -func hasMatchingAttribute*(material: MaterialData, attr: ShaderAttribute): bool = +proc hasMatchingAttribute*(material: MaterialData, attr: ShaderAttribute): bool = return material.attributes.contains(attr.name) and material.attributes[attr.name].theType == attr.theType proc hash*(materialType: MaterialType): Hash = @@ -37,13 +38,30 @@ template `[]`*(material: MaterialData, attributeName: string): DataList = material.attributes[attributeName] - template `[]`*(material: MaterialData, attributeName: string, t: typedesc): ref seq[t] = material.attributes[attributeName][t] - template `[]`*(material: MaterialData, attributeName: string, i: int, t: typedesc): untyped = material.attributes[attributeName][i, t] +template `[]=`*(material: var MaterialData, attribute: string, newList: DataList) = + material.attributes[attribute] = newList + if not material.dirtyAttributes.contains(attribute): + material.dirtyAttributes.add attribute +template `[]=`*[T](material: var MaterialData, attribute: string, newList: seq[T]) = + material.attributes[attribute][] = newList + if not material.dirtyAttributes.contains(attribute): + material.dirtyAttributes.add attribute +template `[]=`*[T](material: var MaterialData, attribute: string, i: int, newValue: T) = + material.attributes[attribute][i] = newValue + if not material.dirtyAttributes.contains(attribute): + material.dirtyAttributes.add attribute + +func dirtyAttributes*(material: MaterialData): seq[string] = + material.dirtyAttributes + +proc clearDirtyAttributes*(material: var MaterialData) = + material.dirtyAttributes.reset + let EMPTY_MATERIAL* = MaterialType( name: "empty material", vertexAttributes: {"position": Vec3F32}.toTable,
--- a/semicongine/mesh.nim Thu Jan 04 21:13:11 2024 +0700 +++ b/semicongine/mesh.nim Sun Jan 07 00:56:44 2024 +0700 @@ -96,7 +96,8 @@ assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) mesh.vertexData[attribute] = initDataList(thetype=getDataType[T]()) mesh.vertexData[attribute].setLen(mesh.vertexCount) - mesh.vertexData[attribute].setValues(value) + mesh.vertexData[attribute] = value + # `=`(mesh.vertexData[attribute], value) proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string, value: T) = initVertexAttribute(mesh, attribute, newSeqWith(mesh.vertexCount, value)) proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string) = @@ -114,7 +115,7 @@ assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) mesh.instanceData[attribute] = initDataList(thetype=getDataType[T]()) mesh.instanceData[attribute].setLen(mesh.instanceCount) - mesh.instanceData[attribute].setValues(value) + mesh.instanceData[attribute] = value proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string, value: T) = initInstanceAttribute(mesh, attribute, newSeqWith(mesh.instanceCount, value)) proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string) = @@ -237,11 +238,11 @@ of Small: rawData(mesh.smallIndices) of Big: rawData(mesh.bigIndices) -func getRawData*(mesh: var MeshObject, attribute: string): (pointer, int) = +func getPointer*(mesh: var MeshObject, attribute: string): pointer = if mesh.vertexData.contains(attribute): - mesh.vertexData[attribute].getRawData() + mesh.vertexData[attribute].getPointer() elif mesh.instanceData.contains(attribute): - mesh.instanceData[attribute].getRawData() + mesh.instanceData[attribute].getPointer() else: raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") @@ -263,12 +264,17 @@ template `[]`*(mesh: MeshObject, attribute: string, t: typedesc): ref seq[t] = getAttribute[t](mesh, attribute) -template `[]`*(mesh: Mesh, attribute: string, t: typedesc): ref seq[t] = - getAttribute[t](mesh[], attribute) template `[]`*(mesh: MeshObject, attribute: string, i: int, t: typedesc): untyped = getAttribute[t](mesh, attribute, i) +template `[]=`*[T](mesh: MeshObject, attribute: string, value: seq[T]) = + getAttribute[t](mesh, attribute) +template `[]=`*[T](mesh: MeshObject, attribute: string, i: int, value: T) = + getAttribute[t](mesh, attribute, i) + +template `[]`*(mesh: Mesh, attribute: string, t: typedesc): ref seq[t] = + mesh[][attribute, t] template `[]`*(mesh: Mesh, attribute: string, i: int, t: typedesc): untyped = - getAttribute[t](mesh[], attribute, i) + mesh[][attribute, i, t] proc updateAttributeData[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: DataList) = if mesh.vertexData.contains(attribute): @@ -287,10 +293,10 @@ proc updateAttributeData[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: seq[T]) = if mesh.vertexData.contains(attribute): assert data.len == mesh.vertexCount - setValues(mesh.vertexData[attribute], data) + mesh.vertexData[attribute] = data elif mesh.instanceData.contains(attribute): assert data.len == mesh.instanceCount - setValues(mesh.instanceData[attribute], data) + mesh.instanceData[attribute] = data else: raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") if not mesh.dirtyAttributes.contains(attribute): @@ -299,10 +305,10 @@ proc updateAttributeData[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, i: int, value: T) = if mesh.vertexData.contains(attribute): assert i < mesh.vertexData[attribute].len - setValue(mesh.vertexData[attribute], i, value) + mesh.vertexData[attribute][i] = value elif mesh.instanceData.contains(attribute): assert i < mesh.instanceData[attribute].len - setValue(mesh.instanceData[attribute], i, value) + mesh.instanceData[attribute][i] = value else: raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") if not mesh.dirtyAttributes.contains(attribute): @@ -372,19 +378,18 @@ proc transform*[T: GPUType](mesh: var MeshObject, attribute: string, transform: Mat4) = if mesh.vertexData.contains(attribute): for i in 0 ..< mesh.vertexData[attribute].len: - setValue(mesh.vertexData[attribute], i, transform * mesh.vertexData[attribute][i, T]) + mesh.vertexData[attribute][i] = transform * mesh.vertexData[attribute][i, T] elif mesh.instanceData.contains(attribute): for i in 0 ..< mesh.instanceData[attribute].len: - setValue(mesh.instanceData[attribute], i, transform * mesh.vertexData[attribute][i, T]) + mesh.instanceData[attribute][i] = transform * mesh.vertexData[attribute][i, T] else: raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") proc applyTransformToVertices*(mesh: var MeshObject, positionAttribute=DEFAULT_POSITION_ATTRIBUTE) = for i in 0 ..< mesh.vertexData[positionAttribute].len: - setValue(mesh.vertexData[positionAttribute], i, mesh.transform * mesh.vertexData[positionAttribute][i, Vec3f]) + mesh.vertexData[positionAttribute][i] = mesh.transform * mesh.vertexData[positionAttribute][i, Vec3f] mesh.transform = Unit4 - func getCollisionPoints*(mesh: MeshObject, positionAttribute=DEFAULT_POSITION_ATTRIBUTE): seq[Vec3f] = for p in mesh[positionAttribute, Vec3f][]: result.add mesh.transform * p
--- a/semicongine/renderer.nim Thu Jan 04 21:13:11 2024 +0700 +++ b/semicongine/renderer.nim Sun Jan 07 00:56:44 2024 +0700 @@ -213,8 +213,7 @@ for attribute in inputs: scenedata.vertexBufferOffsets[(mesh, attribute.name)] = perLocationOffsets[attribute.memoryPerformanceHint] if mesh[].attributes.contains(attribute.name): - let size = mesh[].getRawData(attribute.name)[1] - perLocationOffsets[attribute.memoryPerformanceHint] += size + perLocationOffsets[attribute.memoryPerformanceHint] += mesh[].attributeSize(attribute.name) if perLocationOffsets[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT != 0: perLocationOffsets[attribute.memoryPerformanceHint] += VERTEX_ATTRIB_ALIGNMENT - (perLocationOffsets[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT) @@ -322,9 +321,12 @@ if not (attribute in renderer.scenedata[scene].attributeLocation): return - let (pdata, size) = mesh[].getRawData(attribute) let memoryPerformanceHint = renderer.scenedata[scene].attributeLocation[attribute] - renderer.scenedata[scene].vertexBuffers[memoryPerformanceHint].setData(pdata, size, renderer.scenedata[scene].vertexBufferOffsets[(mesh, attribute)]) + renderer.scenedata[scene].vertexBuffers[memoryPerformanceHint].setData( + mesh[].getPointer(attribute), + mesh[].attributeSize(attribute), + renderer.scenedata[scene].vertexBufferOffsets[(mesh, attribute)] + ) proc updateMeshData*(renderer: var Renderer, scene: var Scene, forceAll=false) = assert scene in renderer.scenedata @@ -340,13 +342,10 @@ proc updateUniformData*(renderer: var Renderer, scene: var Scene, forceAll=false) = assert scene in renderer.scenedata - # TODO: maybe check for dirty materials too, but atm we copy materials into the - # renderers scenedata, so they are immutable after initialization, would - # need to allow updates of materials too in order to make sense let dirty = scene.dirtyShaderGlobals - if not forceAll and dirty.len == 0: - return + # if not forceAll and dirty.len == 0: + # return if forceAll: debug "Update uniforms because 'forceAll' was given" @@ -361,6 +360,10 @@ renderer.scenedata[scene].uniformBuffers.hasKey(shaderPipeline.vk) and renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk].len != 0 ): + var dirtyMaterialAttribs: seq[string] + for material in renderer.scenedata[scene].materials[materialType].mitems: + dirtyMaterialAttribs.add material.dirtyAttributes + material.clearDirtyAttributes() assert renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk][renderer.swapchain.currentInFlight].vk.valid if forceAll: for buffer in renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk]: @@ -369,7 +372,7 @@ var offset = 0 # loop over all uniforms of the shader-shaderPipeline for uniform in shaderPipeline.uniforms: - if dirty.contains(uniform.name) or forceAll: # only update uniforms if necessary + if dirty.contains(uniform.name) or dirtyMaterialAttribs.contains(uniform.name) or forceAll: # only update uniforms if necessary var value = initDataList(uniform.theType) if scene.shaderGlobals.hasKey(uniform.name): assert scene.shaderGlobals[uniform.name].thetype == uniform.thetype @@ -382,14 +385,13 @@ foundValue = true assert foundValue, &"Uniform '{uniform.name}' not found in scene shaderGlobals or materials" assert (uniform.arrayCount == 0 and value.len == 1) or value.len == uniform.arrayCount, &"Uniform '{uniform.name}' found has wrong length (shader declares {uniform.arrayCount} but shaderGlobals and materials provide {value.len})" - let (pdata, size) = value.getRawData() - assert size == uniform.size, "During uniform update: gathered value has size {size} but uniform expects size {uniform.size}" + assert value.size == uniform.size, "During uniform update: gathered value has size {value.size} but uniform expects size {uniform.size}" debug &" update uniform {uniform.name} with value: {value}" # TODO: technically we would only need to update the uniform buffer of the current # frameInFlight (I think), but we don't track for which frame the shaderglobals are no longer dirty # therefore we have to update the uniform values in all buffers, of all inFlightframes (usually 2) for buffer in renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk]: - buffer.setData(pdata, size, offset) + buffer.setData(value.getPointer(), value.size, offset) offset += uniform.size scene.clearDirtyShaderGlobals()
--- a/semicongine/resources/mesh.nim Thu Jan 04 21:13:11 2024 +0700 +++ b/semicongine/resources/mesh.nim Sun Jan 07 00:56:44 2024 +0700 @@ -116,7 +116,7 @@ let accessorOffset = if accessor.hasKey("byteOffset"): accessor["byteOffset"].getInt() else: 0 let length = bufferView["byteLength"].getInt() let bufferOffset = bufferView["byteOffset"].getInt() + accessorOffset - var dstPointer = result.getRawData()[0] + var dstPointer = result.getPointer() if bufferView.hasKey("byteStride"): warn "Congratulations, you try to test a feature (loading buffer data with stride attributes) that we have no idea where it is used and how it can be tested (need a coresponding *.glb file)." @@ -170,23 +170,23 @@ if defaultMaterial.attributes.contains("color"): attributes["color"] = initDataList(thetype=Vec4F32) if pbr.hasKey(GLTF_MATERIAL_MAPPING["color"]): - setValue(attributes["color"], @[newVec4f( + attributes["color"] = @[newVec4f( pbr[GLTF_MATERIAL_MAPPING["color"]][0].getFloat(), pbr[GLTF_MATERIAL_MAPPING["color"]][1].getFloat(), pbr[GLTF_MATERIAL_MAPPING["color"]][2].getFloat(), pbr[GLTF_MATERIAL_MAPPING["color"]][3].getFloat(), - )]) + )] else: - setValue(attributes["color"], @[newVec4f(1, 1, 1, 1)]) + attributes["color"] = @[newVec4f(1, 1, 1, 1)] # pbr material values for factor in ["metallic", "roughness"]: if defaultMaterial.attributes.contains(factor): attributes[factor] = initDataList(thetype=Float32) if pbr.hasKey(GLTF_MATERIAL_MAPPING[factor]): - setValue(attributes[factor], @[float32(pbr[GLTF_MATERIAL_MAPPING[factor]].getFloat())]) + attributes[factor] = @[float32(pbr[GLTF_MATERIAL_MAPPING[factor]].getFloat())] else: - setValue(attributes[factor], @[0.5'f32]) + attributes[factor] = @[0.5'f32] # pbr material textures for texture in ["baseTexture", "metallicRoughnessTexture"]: @@ -194,11 +194,9 @@ attributes[texture] = initDataList(thetype=TextureType) # attributes[texture & "Index"] = initDataList(thetype=UInt8) if pbr.hasKey(GLTF_MATERIAL_MAPPING[texture]): - setValue(attributes[texture], @[loadTexture(root, pbr[GLTF_MATERIAL_MAPPING[texture]]["index"].getInt(), mainBuffer)]) - # setValue(attributes[texture & "Index"], @[pbr[GLTF_MATERIAL_MAPPING[texture]].getOrDefault("texCoord").getInt(0).uint8]) + attributes[texture] = @[loadTexture(root, pbr[GLTF_MATERIAL_MAPPING[texture]]["index"].getInt(), mainBuffer)] else: - setValue(attributes[texture], @[EMPTY_TEXTURE]) - # setValue(attributes[texture & "Index"], @[0'u8]) + attributes[texture] = @[EMPTY_TEXTURE] # generic material textures for texture in ["normalTexture", "occlusionTexture", "emissiveTexture"]: @@ -206,23 +204,21 @@ attributes[texture] = initDataList(thetype=TextureType) # attributes[texture & "Index"] = initDataList(thetype=UInt8) if materialNode.hasKey(GLTF_MATERIAL_MAPPING[texture]): - setValue(attributes[texture], @[loadTexture(root, materialNode[texture]["index"].getInt(), mainBuffer)]) - # setValue(attributes[texture & "Index"], @[materialNode[texture].getOrDefault("texCoord").getInt(0).uint8]) + attributes[texture] = @[loadTexture(root, materialNode[texture]["index"].getInt(), mainBuffer)] else: - setValue(attributes[texture], @[EMPTY_TEXTURE]) - # setValue(attributes[texture & "Index"], @[0'u8]) + attributes[texture] = @[EMPTY_TEXTURE] # emissiv color if defaultMaterial.attributes.contains("emissiveColor"): attributes["emissiveColor"] = initDataList(thetype=Vec3F32) if materialNode.hasKey(GLTF_MATERIAL_MAPPING["emissiveColor"]): - setValue(attributes["emissiveColor"], @[newVec3f( + attributes["emissiveColor"] = @[newVec3f( materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][0].getFloat(), materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][1].getFloat(), materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][2].getFloat(), - )]) + )] else: - setValue(attributes["emissiveColor"], @[newVec3f(1'f32, 1'f32, 1'f32)]) + attributes["emissiveColor"] = @[newVec3f(1'f32, 1'f32, 1'f32)] result = initMaterialData(theType=defaultMaterial, name=materialNode["name"].getStr(), attributes=attributes)
--- a/semicongine/scene.nim Thu Jan 04 21:13:11 2024 +0700 +++ b/semicongine/scene.nim Sun Jan 07 00:56:44 2024 +0700 @@ -46,7 +46,7 @@ proc addShaderGlobal*[T](scene: var Scene, name: string, data: T) = assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add shader values" scene.shaderGlobals[name] = initDataList(thetype=getDataType[T]()) - setValues(scene.shaderGlobals[name], @[data]) + scene.shaderGlobals[name] = @[data] scene.dirtyShaderGlobals.add name proc addShaderGlobalArray*[T](scene: var Scene, name: string, data: openArray[T]) = @@ -61,12 +61,12 @@ scene.shaderGlobals[name][T] proc setShaderGlobal*[T](scene: var Scene, name: string, value: T) = - setValues[T](scene.shaderGlobals[name], @[value]) + scene.shaderGlobals[name] = @[value] if not scene.dirtyShaderGlobals.contains(name): scene.dirtyShaderGlobals.add name proc setShaderGlobalArray*[T](scene: var Scene, name: string, value: seq[T]) = - setValues[T](scene.shaderGlobals[name], value) + scene.shaderGlobals[name] = value if not scene.dirtyShaderGlobals.contains(name): scene.dirtyShaderGlobals.add name