Mercurial > games > semicongine
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 ) |