comparison 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
comparison
equal deleted inserted replaced
1217:f819a874058f 1218:56781cc0fc7c
1 import std/tables
2 import std/strformat
3 import std/strutils
4
5 import ./core
6 import ./vulkan/shader
7
8 type
9 MaterialType* = object
10 name*: string
11 vertexAttributes*: Table[string, DataType]
12 instanceAttributes*: Table[string, DataType]
13 attributes*: Table[string, DataType]
14 MaterialData* = ref object # needs to be ref, so we can update stuff from other locations
15 theType*: MaterialType
16 name*: string
17 attributes: Table[string, DataList]
18 dirtyAttributes: seq[string]
19
20 proc HasMatchingAttribute*(materialType: MaterialType, attr: ShaderAttribute): bool =
21 return materialType.attributes.contains(attr.name) and materialType.attributes[attr.name] == attr.theType
22
23 proc HasMatchingAttribute*(material: MaterialData, attr: ShaderAttribute): bool =
24 return material.attributes.contains(attr.name) and material.attributes[attr.name].theType == attr.theType
25
26 template `[]`*(material: MaterialData, attributeName: string): DataList =
27 material.attributes[attributeName]
28 template `[]`*(material: MaterialData, attributeName: string, t: typedesc): ref seq[t] =
29 material.attributes[attributeName][t]
30 template `[]`*(material: MaterialData, attributeName: string, i: int, t: typedesc): untyped =
31 material.attributes[attributeName][i, t]
32
33 template `[]=`*(material: var MaterialData, attribute: string, newList: DataList) =
34 material.attributes[attribute] = newList
35 if not material.dirtyAttributes.contains(attribute):
36 material.dirtyAttributes.add attribute
37 template `[]=`*[T](material: var MaterialData, attribute: string, newList: seq[T]) =
38 material.attributes[attribute][] = newList
39 if not material.dirtyAttributes.contains(attribute):
40 material.dirtyAttributes.add attribute
41 template `[]=`*[T](material: var MaterialData, attribute: string, i: int, newValue: T) =
42 material.attributes[attribute][i] = newValue
43 if not material.dirtyAttributes.contains(attribute):
44 material.dirtyAttributes.add attribute
45
46 func DirtyAttributes*(material: MaterialData): seq[string] =
47 material.dirtyAttributes
48
49 proc ClearDirtyAttributes*(material: var MaterialData) =
50 material.dirtyAttributes.reset
51
52 proc `$`*(materialType: MaterialType): string =
53 return materialType.name
54
55 proc AssertCanRender*(shader: ShaderConfiguration, materialType: MaterialType) =
56 for attr in shader.inputs:
57 if attr.perInstance:
58 if attr.name in [TRANSFORM_ATTRIB, MATERIALINDEX_ATTRIBUTE]:
59 continue
60 assert materialType.instanceAttributes.contains(attr.name), &"MaterialType '{materialType}' requires instance attribute '{attr.name}' in order to be renderable with the assigned shader '{shader}'"
61 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}'"
62 else:
63 assert materialType.vertexAttributes.contains(attr.name), &"MaterialType '{materialType}' requires vertex attribute '{attr.name}' in order to be renderable with the assigned shader '{shader}'"
64 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}'"
65
66 proc `$`*(material: MaterialData): string =
67 var attributes: seq[string]
68 for key, value in material.attributes.pairs:
69 attributes.add &"{key}: {value}"
70 return &"""{material.name}: [{attributes.join(", ")}]"""
71
72 proc InitMaterialData*(
73 theType: MaterialType,
74 name: string,
75 attributes: Table[string, DataList],
76 ): MaterialData =
77 var theName = name
78 if theName == "":
79 theName = &"material instance of '{theType}'"
80 for matName, theType in theType.attributes.pairs:
81 assert attributes.contains(matName), &"missing material attribute '{matName}' for {theType}"
82 assert attributes[matName].theType == theType
83 MaterialData(
84 theType: theType,
85 name: theName,
86 attributes: attributes,
87 )
88
89 proc InitMaterialData*(
90 theType: MaterialType,
91 name: string = "",
92 attributes: openArray[(string, DataList)] = @[],
93 ): MaterialData =
94 var theName = name
95 if theName == "":
96 theName = &"material instance of '{theType}'"
97 InitMaterialData(theType = theType, name = theName, attributes = attributes.toTable)
98
99 const
100 VERTEX_COLORED_MATERIAL* = MaterialType(
101 name: "vertex color material",
102 vertexAttributes: {
103 "position": Vec3F32,
104 "color": Vec4F32,
105 }.toTable,
106 )
107 SINGLE_COLOR_MATERIAL* = MaterialType(
108 name: "single color material",
109 vertexAttributes: {
110 "position": Vec3F32,
111 }.toTable,
112 attributes: {"color": Vec4F32}.toTable
113 )
114 SINGLE_TEXTURE_MATERIAL* = MaterialType(
115 name: "single texture material",
116 vertexAttributes: {
117 "position": Vec3F32,
118 "uv": Vec2F32,
119 }.toTable,
120 attributes: {"baseTexture": TextureType}.toTable
121 )
122 COLORED_SINGLE_TEXTURE_MATERIAL* = MaterialType(
123 name: "colored single texture material",
124 vertexAttributes: {
125 "position": Vec3F32,
126 "uv": Vec2F32,
127 }.toTable,
128 attributes: {"baseTexture": TextureType, "color": Vec4F32}.toTable
129 )
130 EMPTY_MATERIAL* = MaterialType(
131 name: "empty material",
132 vertexAttributes: {"position": Vec3F32}.toTable,
133 instanceAttributes: {TRANSFORM_ATTRIB: Mat4F32}.toTable,
134 )
135 EMPTY_SHADER* = CreateShaderConfiguration(
136 name = "empty shader",
137 inputs = [
138 Attr[Mat4](TRANSFORM_ATTRIB, memoryPerformanceHint = PreferFastWrite, perInstance = true),
139 Attr[Vec3f]("position", memoryPerformanceHint = PreferFastRead),
140 ],
141 outputs = [Attr[Vec4f]("color")],
142 vertexCode = &"gl_Position = vec4(position, 1.0) * {TRANSFORM_ATTRIB};",
143 fragmentCode = &"color = vec4(1, 0, 1, 1);"
144 )