Lugdunum  0.1.0
ShaderBuilder.cpp
Go to the documentation of this file.
2 
3 #include <fstream>
4 
5 #if defined(LUG_SYSTEM_ANDROID)
6  #include <android/asset_manager.h>
7 
9  #include <lug/Window/Window.hpp>
10 #endif
11 
12 #include <shaderc/shaderc.hpp>
13 
14 #include <lug/System/Exception.hpp>
15 
16 namespace lug {
17 namespace Graphics {
18 namespace Vulkan {
19 namespace Render {
20 
22  std::string shaderRoot,
25  Pipeline::Id id) {
26  switch (technique) {
27  case ::lug::Graphics::Render::Technique::Type::Forward:
28  switch (type) {
30  return Pipeline::ShaderBuilder::buildShaderFromFile(shaderRoot + "forward/shader.vert", type, id);
32  return Pipeline::ShaderBuilder::buildShaderFromFile(shaderRoot + "forward/shader.frag", type, id);
33  }
34  }
35 
36  return {};
37 }
38 
39 std::vector<uint32_t> Pipeline::ShaderBuilder::buildShaderFromFile(std::string filename, Pipeline::ShaderBuilder::Type type, Pipeline::Id id) {
40 #if defined(LUG_SYSTEM_ANDROID)
41  // Load shader from compressed asset
42  AAsset* asset = AAssetManager_open((lug::Window::priv::WindowImpl::activity)->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
43 
44  if (!asset) {
45  LUG_EXCEPT(FileNotFoundException, "Can't open Android asset");
46  return {};
47  }
48 
49  uint32_t size = AAsset_getLength(asset);
50 
51  if (size <= 0) {
52  LUG_EXCEPT(FileNotFoundException, "Android asset is empty");
53  return {};
54  }
55 
56  std::string content;
57  content.resize(size);
58 
59  AAsset_read(asset, reinterpret_cast<char*>(&content[0]), size);
60  AAsset_close(asset);
61 #else
62  std::ifstream file(filename);
63 
64  if (!file.good()) {
65  LUG_EXCEPT(FileNotFoundException, "Can't find shader file");
66  }
67 
68  std::string content = std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
69 #endif
70 
71  return Pipeline::ShaderBuilder::buildShaderFromString(filename, content, type, id);
72 }
73 
74 std::vector<uint32_t> Pipeline::ShaderBuilder::buildShaderFromString(std::string filename, std::string content, Pipeline::ShaderBuilder::Type type, Pipeline::Id id) {
75  shaderc::Compiler compiler;
76  shaderc::CompileOptions options;
77 
78  // Set macros according to the pipeline ID
79  {
80  Pipeline::Id::PrimitivePart primitivePart = id.getPrimitivePart();
81  Pipeline::Id::MaterialPart materialPart = id.getMaterialPart();
82  Pipeline::Id::ExtraPart extraPart = id.getExtraPart();
83 
84  // Set the display mode
85  options.AddMacroDefinition("DISPLAY_MODE", std::to_string(static_cast<uint8_t>(extraPart.displayMode)));
86 
87  // Primitive part
88  {
89  options.AddMacroDefinition("IN_POSITION", std::to_string(primitivePart.positionVertexData));
90  options.AddMacroDefinition("IN_NORMAL", std::to_string(primitivePart.normalVertexData));
91  options.AddMacroDefinition("IN_TANGENT", std::to_string(primitivePart.tangentVertexData));
92  options.AddMacroDefinition("IN_UV", std::to_string(primitivePart.countTexCoord));
93  options.AddMacroDefinition("IN_COLOR", std::to_string(primitivePart.countColor));
94  }
95 
96  // Material Part
97  {
98  options.AddMacroDefinition("TEXTURE_COLOR", materialPart.baseColorInfo != 0b11 ? "1" : "0");
99  options.AddMacroDefinition("TEXTURE_COLOR_UV", "inUV" + std::to_string(materialPart.baseColorInfo));
100 
101  options.AddMacroDefinition("TEXTURE_METALLIC_ROUGHNESS", materialPart.metallicRoughnessInfo != 0b11 ? "1" : "0");
102  options.AddMacroDefinition("TEXTURE_METALLIC_ROUGHNESS_UV", "inUV" + std::to_string(materialPart.metallicRoughnessInfo));
103 
104  options.AddMacroDefinition("TEXTURE_NORMAL", materialPart.normalInfo != 0b11 ? "1" : "0");
105  options.AddMacroDefinition("TEXTURE_NORMAL_UV", "inUV" + std::to_string(materialPart.normalInfo));
106 
107  options.AddMacroDefinition("TEXTURE_OCCLUSION", materialPart.occlusionInfo != 0b11 ? "1" : "0");
108  options.AddMacroDefinition("TEXTURE_OCCLUSION_UV", "inUV" + std::to_string(materialPart.occlusionInfo));
109 
110  options.AddMacroDefinition("TEXTURE_EMISSIVE", materialPart.emissiveInfo != 0b11 ? "1" : "0");
111  options.AddMacroDefinition("TEXTURE_EMISSIVE_UV", "inUV" + std::to_string(materialPart.emissiveInfo));
112  }
113 
114  // Indirect lightning part
115  {
116  options.AddMacroDefinition("TEXTURE_IRRADIANCE_MAP", extraPart.irradianceMapInfo ? "1" : "0");
117  options.AddMacroDefinition("TEXTURE_PREFILTERED_MAP", extraPart.prefilteredMapInfo ? "1" : "0");
118  }
119 
120  // Set location
121  {
122  uint8_t location = 2;
123 
124  if (primitivePart.tangentVertexData) {
125  options.AddMacroDefinition("IN_TANGENT_LOCATION", std::to_string(location++));
126  }
127 
128  for (uint8_t i = 0; i < primitivePart.countTexCoord; ++i) {
129  options.AddMacroDefinition("IN_UV_" + std::to_string(i) + "_LOCATION", std::to_string(location++));
130  }
131 
132  for (uint8_t i = 0; i < primitivePart.countColor; ++i) {
133  options.AddMacroDefinition("IN_COLOR_" + std::to_string(i) + "_LOCATION", std::to_string(location++));
134  }
135 
136  options.AddMacroDefinition("IN_FREE_LOCATION", std::to_string(location++));
137  }
138 
139  // Set binding
140  {
141  uint8_t binding = 0;
142 
143  if (materialPart.baseColorInfo != 0b11) {
144  options.AddMacroDefinition("TEXTURE_COLOR_BINDING", std::to_string(binding++));
145  }
146 
147  if (materialPart.metallicRoughnessInfo != 0b11) {
148  options.AddMacroDefinition("TEXTURE_METALLIC_ROUGHNESS_BINDING", std::to_string(binding++));
149  }
150 
151  if (materialPart.normalInfo != 0b11) {
152  options.AddMacroDefinition("TEXTURE_NORMAL_BINDING", std::to_string(binding++));
153  }
154 
155  if (materialPart.occlusionInfo != 0b11) {
156  options.AddMacroDefinition("TEXTURE_OCCLUSION_BINDING", std::to_string(binding++));
157  }
158 
159  if (materialPart.emissiveInfo != 0b11) {
160  options.AddMacroDefinition("TEXTURE_EMISSIVE_BINDING", std::to_string(binding++));
161  }
162 
163  if (extraPart.irradianceMapInfo) {
164  options.AddMacroDefinition("TEXTURE_IRRADIANCE_MAP_BINDING", std::to_string(binding++));
165  }
166 
167  if (extraPart.prefilteredMapInfo) {
168  options.AddMacroDefinition("TEXTURE_BRDF_LUT_BINDING", std::to_string(binding++));
169  options.AddMacroDefinition("TEXTURE_PREFILTERED_MAP_BINDING", std::to_string(binding++));
170  }
171  }
172  }
173 
174  shaderc_shader_kind kind = [](Pipeline::ShaderBuilder::Type type) {
175  switch (type) {
177  return shaderc_glsl_vertex_shader;
179  return shaderc_glsl_fragment_shader;
180  }
181 
182  return shaderc_shader_kind{};
183  }(type);
184 
185  shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(content, kind, filename.c_str(), options);
186 
187  if (module.GetCompilationStatus() != shaderc_compilation_status_success) {
188  LUG_EXCEPT(InternalErrorException, module.GetErrorMessage());
189  }
190 
191  std::vector<uint32_t> result(module.cbegin(), module.cend());
192  return result;
193 }
194 
195 } // Render
196 } // Vulkan
197 } // Graphics
198 } // lug
Id of the Pipeline. It&#39;s a concatenation of three parts: PrimitivePart, MaterialPart and PipelinePart...
Definition: Pipeline.hpp:33
Describes the material. How is the material composed, with textures, no textures, etc...
Definition: Pipeline.hpp:61
uint32_t occlusionInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:67
uint32_t countColor
The number of colors (maximum 3).
Definition: Pipeline.hpp:44
uint32_t baseColorInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:64
uint32_t positionVertexData
0 if no attribute position.
Definition: Pipeline.hpp:40
static std::vector< uint32_t > buildShaderFromFile(std::string filename, Type type, Pipeline::Id id)
uint32_t irradianceMapInfo
1 texture, 0 no texture.
Definition: Pipeline.hpp:83
static ANativeActivity * activity
uint32_t displayMode
Corresponding to the value in Renderer::DisplayMode.
Definition: Pipeline.hpp:82
static std::vector< uint32_t > buildShaderFromString(std::string filename, std::string content, Type type, Pipeline::Id id)
static std::vector< uint32_t > buildShader(std::string shaderRoot, ::lug::Graphics::Render::Technique::Type technique, Type type, Pipeline::Id id)
uint32_t emissiveInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:68
uint32_t normalVertexData
0 if no attribute normal.
Definition: Pipeline.hpp:41
uint32_t metallicRoughnessInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:65
#define LUG_EXCEPT(type, desc)
Definition: Exception.hpp:124
uint32_t prefilteredMapInfo
1 texture, 0 no texture
Definition: Pipeline.hpp:84
uint32_t normalInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:66
uint32_t tangentVertexData
0 if no attribute tangeant.
Definition: Pipeline.hpp:42
uint32_t countTexCoord
The number of texcoord (maximum 3).
Definition: Pipeline.hpp:43