Mercurial > games > semicongine
diff semiconginev2/old/material.nim @ 1218:56781cc0fc7c compiletime-tests
did: renamge main package
author | sam <sam@basx.dev> |
---|---|
date | Wed, 17 Jul 2024 21:01:37 +0700 |
parents | semicongine/old/material.nim@a3eb305bcac2 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semiconginev2/old/material.nim Wed Jul 17 21:01:37 2024 +0700 @@ -0,0 +1,144 @@ +import std/tables +import std/strformat +import std/strutils + +import ./core +import ./vulkan/shader + +type + MaterialType* = object + name*: string + vertexAttributes*: Table[string, DataType] + instanceAttributes*: Table[string, DataType] + attributes*: Table[string, DataType] + MaterialData* = ref object # needs to be ref, so we can update stuff from other locations + theType*: MaterialType + name*: string + attributes: Table[string, DataList] + dirtyAttributes: seq[string] + +proc HasMatchingAttribute*(materialType: MaterialType, attr: ShaderAttribute): bool = + return materialType.attributes.contains(attr.name) and materialType.attributes[attr.name] == attr.theType + +proc HasMatchingAttribute*(material: MaterialData, attr: ShaderAttribute): bool = + return material.attributes.contains(attr.name) and material.attributes[attr.name].theType == attr.theType + +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 + +proc `$`*(materialType: MaterialType): string = + return materialType.name + +proc AssertCanRender*(shader: ShaderConfiguration, materialType: MaterialType) = + for attr in shader.inputs: + if attr.perInstance: + if attr.name in [TRANSFORM_ATTRIB, MATERIALINDEX_ATTRIBUTE]: + continue + assert materialType.instanceAttributes.contains(attr.name), &"MaterialType '{materialType}' requires instance attribute '{attr.name}' in order to be renderable with the assigned shader '{shader}'" + assert materialType.instanceAttributes[attr.name] == attr.theType, &"Instance attribute '{attr.name}' of MaterialType '{materialType}' is of type {materialType.instanceAttributes[attr.name]} but assigned shader '{shader}' declares type '{attr.theType}'" + else: + assert materialType.vertexAttributes.contains(attr.name), &"MaterialType '{materialType}' requires vertex attribute '{attr.name}' in order to be renderable with the assigned shader '{shader}'" + assert materialType.vertexAttributes[attr.name] == attr.theType, &"Vertex attribute '{attr.name}' of MaterialType '{materialType}' is of type {materialType.vertexAttributes[attr.name]} but assigned shader '{shader}' declares type '{attr.theType}'" + +proc `$`*(material: MaterialData): string = + var attributes: seq[string] + for key, value in material.attributes.pairs: + attributes.add &"{key}: {value}" + return &"""{material.name}: [{attributes.join(", ")}]""" + +proc InitMaterialData*( + theType: MaterialType, + name: string, + attributes: Table[string, DataList], +): MaterialData = + var theName = name + if theName == "": + theName = &"material instance of '{theType}'" + for matName, theType in theType.attributes.pairs: + assert attributes.contains(matName), &"missing material attribute '{matName}' for {theType}" + assert attributes[matName].theType == theType + MaterialData( + theType: theType, + name: theName, + attributes: attributes, + ) + +proc InitMaterialData*( + theType: MaterialType, + name: string = "", + attributes: openArray[(string, DataList)] = @[], +): MaterialData = + var theName = name + if theName == "": + theName = &"material instance of '{theType}'" + InitMaterialData(theType = theType, name = theName, attributes = attributes.toTable) + +const + VERTEX_COLORED_MATERIAL* = MaterialType( + name: "vertex color material", + vertexAttributes: { + "position": Vec3F32, + "color": Vec4F32, + }.toTable, + ) + SINGLE_COLOR_MATERIAL* = MaterialType( + name: "single color material", + vertexAttributes: { + "position": Vec3F32, + }.toTable, + attributes: {"color": Vec4F32}.toTable + ) + SINGLE_TEXTURE_MATERIAL* = MaterialType( + name: "single texture material", + vertexAttributes: { + "position": Vec3F32, + "uv": Vec2F32, + }.toTable, + attributes: {"baseTexture": TextureType}.toTable + ) + COLORED_SINGLE_TEXTURE_MATERIAL* = MaterialType( + name: "colored single texture material", + vertexAttributes: { + "position": Vec3F32, + "uv": Vec2F32, + }.toTable, + attributes: {"baseTexture": TextureType, "color": Vec4F32}.toTable + ) + EMPTY_MATERIAL* = MaterialType( + name: "empty material", + vertexAttributes: {"position": Vec3F32}.toTable, + instanceAttributes: {TRANSFORM_ATTRIB: Mat4F32}.toTable, + ) + EMPTY_SHADER* = CreateShaderConfiguration( + name = "empty shader", + inputs = [ + Attr[Mat4](TRANSFORM_ATTRIB, memoryPerformanceHint = PreferFastWrite, perInstance = true), + Attr[Vec3f]("position", memoryPerformanceHint = PreferFastRead), + ], + outputs = [Attr[Vec4f]("color")], + vertexCode = &"gl_Position = vec4(position, 1.0) * {TRANSFORM_ATTRIB};", + fragmentCode = &"color = vec4(1, 0, 1, 1);" + )