comparison src/zamikongine/shader.nim @ 493:680c4b8ca28a

add: working implementation of uniforms
author Sam <sam@basx.dev>
date Sat, 14 Jan 2023 23:34:50 +0700
parents 54a1f8ee208e
children 0c18638c7217
comparison
equal deleted inserted replaced
492:d63d980fa3bb 493:680c4b8ca28a
3 import std/tables 3 import std/tables
4 import std/compilesettings 4 import std/compilesettings
5 5
6 6
7 import ./vulkan_helpers 7 import ./vulkan_helpers
8 import ./glsl_helpers
8 import ./vulkan 9 import ./vulkan
9 import ./vertex 10 import ./vertex
11 import ./descriptor
10 import ./math/vector 12 import ./math/vector
11 13
12 type 14 type
13 AllowedUniformType = SomeNumber|Vec 15 AllowedUniformType = SomeNumber|Vec
14 UniformSlot *[T:AllowedUniformType] = object 16 UniformSlot *[T:AllowedUniformType] = object
15 ShaderProgram*[Uniforms] = object 17 ShaderProgram*[VertexType, Uniforms] = object
16 entryPoint*: string 18 entryPoint*: string
17 programType*: VkShaderStageFlagBits 19 programType*: VkShaderStageFlagBits
18 shader*: VkPipelineShaderStageCreateInfo 20 shader*: VkPipelineShaderStageCreateInfo
19 uniforms*: Uniforms 21 uniforms*: Uniforms
20 22
56 (uint32(shaderbinary[i + 2]) shl 16) or 58 (uint32(shaderbinary[i + 2]) shl 16) or
57 (uint32(shaderbinary[i + 3]) shl 24) 59 (uint32(shaderbinary[i + 3]) shl 24)
58 ) 60 )
59 i += 4 61 i += 4
60 62
61 proc initShaderProgram*[T](device: VkDevice, programType: static VkShaderStageFlagBits, shader: static string, entryPoint: static string="main"): ShaderProgram[T] = 63 proc initShaderProgram*[VertexType, Uniforms](device: VkDevice, programType: static VkShaderStageFlagBits, shader: static string, entryPoint: static string="main"): ShaderProgram[VertexType, Uniforms] =
62 result.entryPoint = entryPoint 64 result.entryPoint = entryPoint
63 result.programType = programType 65 result.programType = programType
64 66
65 const constcode = compileGLSLToSPIRV(programType, shader, entryPoint) 67 const constcode = compileGLSLToSPIRV(programType, shader, entryPoint)
66 var code = constcode 68 var code = constcode
77 stage: programType, 79 stage: programType,
78 module: shaderModule, 80 module: shaderModule,
79 pName: cstring(result.entryPoint), # entry point for shader 81 pName: cstring(result.entryPoint), # entry point for shader
80 ) 82 )
81 83
82 func generateVertexShaderCode*[VertexType](entryPoint, positionAttrName, colorAttrName: static string): string {.compileTime.} = 84 func generateVertexShaderCode*[VertexType, Uniforms](
85 shaderBody: static string = "",
86 entryPoint: static string = "main",
87 glslVersion: static string = "450"
88 ): string {.compileTime.} =
83 var lines: seq[string] 89 var lines: seq[string]
84 lines.add "#version 450" 90 lines.add "#version " & glslVersion
85 # lines.add "layout(binding = 0) uniform UniformBufferObject { float dt; } ubo;" 91 lines.add "layout(row_major) uniform;"
86 lines.add generateGLSLDeclarations[VertexType]() 92 lines.add generateGLSLUniformDeclarations[Uniforms]()
93 lines.add generateGLSLVertexDeclarations[VertexType]()
87 lines.add "layout(location = 0) out vec3 fragColor;" 94 lines.add "layout(location = 0) out vec3 fragColor;"
88 lines.add "void " & entryPoint & "() {" 95 lines.add "void " & entryPoint & "() {"
89 96
97 var hasPosition = 0
98 var hasColor = 0
90 for name, value in VertexType().fieldPairs: 99 for name, value in VertexType().fieldPairs:
91 when typeof(value) is VertexAttribute and name == positionAttrName: 100 when typeof(value) is PositionAttribute:
92 # lines.add " vec2 tmp = " & name & " * ubo.dt;" 101 let glsltype = getGLSLType[getAttributeType(value)]()
93 lines.add " vec2 tmp = " & name & ";" 102 lines.add &" {glsltype} in_position = " & name & ";"
94 lines.add " gl_Position = vec4(tmp, 0.0, 1.0);" 103 if getAttributeType(value) is Vec2:
95 when typeof(value) is VertexAttribute and name == colorAttrName: 104 lines.add " vec4 out_position = vec4(in_position, 0.0, 1.0);"
96 lines.add " fragColor = " & name & ";" 105 elif getAttributeType(value) is Vec3:
106 lines.add " vec4 out_position = vec4(in_position, 1.0);"
107 elif getAttributeType(value) is Vec4:
108 lines.add " vec4 out_position = in_position;"
109 hasPosition += 1
110 when typeof(value) is ColorAttribute:
111 let glsltype = getGLSLType[getAttributeType(value)]()
112 lines.add &" {glsltype} in_color = " & name & ";"
113 lines.add &" {glsltype} out_color = in_color;";
114 hasColor += 1
115
116 lines.add shaderBody
117 lines.add " gl_Position = out_position;"
118 lines.add " fragColor = out_color;"
97 lines.add "}" 119 lines.add "}"
120 if hasPosition != 1:
121 raise newException(Exception, fmt"VertexType needs to have exactly one attribute of type PositionAttribute (has {hasPosition})")
122 if hasColor != 1:
123 raise newException(Exception, fmt"VertexType needs to have exactly one attribute of type ColorAttribute (has {hasColor})")
98 return lines.join("\n") 124 return lines.join("\n")
99 125
100 func generateFragmentShaderCode*[VertexType](entryPoint: static string): string {.compileTime.} = 126 func generateFragmentShaderCode*[VertexType](
127 shaderBody: static string = "",
128 entryPoint: static string = "main",
129 glslVersion: static string = "450"
130 ): string {.compileTime.} =
101 var lines: seq[string] 131 var lines: seq[string]
102 lines.add "#version 450" 132 lines.add "#version " & glslVersion
133 lines.add "layout(row_major) uniform;"
103 lines.add "layout(location = 0) in vec3 fragColor;" 134 lines.add "layout(location = 0) in vec3 fragColor;"
104 lines.add "layout(location = 0) out vec4 outColor;" 135 lines.add "layout(location = 0) out vec4 outColor;"
105 lines.add "void " & entryPoint & "() {" 136 lines.add "void " & entryPoint & "() {"
106 lines.add " outColor = vec4(fragColor, 1.0);" 137 lines.add " vec3 in_color = fragColor;"
138 lines.add " vec3 out_color = in_color;"
139 lines.add shaderBody
140 lines.add " outColor = vec4(out_color, 1.0);"
107 lines.add "}" 141 lines.add "}"
108 142
109 return lines.join("\n") 143 return lines.join("\n")