Mercurial > games > semicongine
view semicongine/material.nim @ 438:1ab09f8cc68d
did: refactor and improve packaging API
author | Sam <sam@basx.dev> |
---|---|
date | Wed, 14 Feb 2024 21:58:43 +0700 |
parents | 36b907544820 |
children | ab406a0d1551 |
line wrap: on
line source
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 = var attributes: seq[string] for key, value in materialType.attributes.pairs: attributes.add &"{key}: {value}" return &"""MaterialType '{materialType.name}' | Attributes: {attributes.join(", ")}""" proc `$`*(material: MaterialData): string = var attributes: seq[string] for key, value in material.attributes.pairs: attributes.add &"{key}: {value}" return &"""Material '{material.name}' | Attributes: {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 EMPTY_MATERIAL* = MaterialType( name: "empty material", vertexAttributes: {"position": Vec3F32}.toTable, ) COLORED_MATERIAL* = MaterialType( name: "single color material", vertexAttributes: {"position": Vec3F32}.toTable, attributes: {"color": Vec4F32}.toTable, ) 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_SHADER* = createShaderConfiguration( 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);" )