TerraForge3D  2.3.1
3D Terrain And Landscape Generator
ShadingManager.cpp
1#include "Shading/ShadingManager.h"
2#include "Utils/Utils.h"
3#include "Data/ApplicationState.h"
4#include "Profiler.h"
5#include "Platform.h"
6#include "imgui/imgui.h"
7// #include "glsl_optimizer.h"
8
9#include "Shading/ShaderNodes/ShaderOutputNode.h"
10#include "Shading/ShaderNodes/ShaderTextureNode.h"
11#include "Shading/ShaderNodes/Float3Node.h"
12#include "Shading/ShaderNodes/FloatNode.h"
13#include "Shading/ShaderNodes/PBRMaterialNode.h"
14#include "Shading/ShaderNodes/CustomShaderNode.h"
15#include "Shading/ShaderNodes/BakeToSlotNode.h"
16
17
18#include <filesystem>
19namespace fs = std::filesystem;
20
21static char *stristr4(const char *str, const char *pattern)
22{
23 size_t i;
24
25 if (!*pattern)
26 {
27 return (char *)str;
28 }
29
30 for (; *str; str++)
31 {
32 if (toupper((unsigned char)*str) == toupper((unsigned char)*pattern))
33 {
34 for (i = 1;; i++)
35 {
36 if (!pattern[i])
37 {
38 return (char *)str;
39 }
40
41 if (toupper((unsigned char)str[i]) != toupper((unsigned char)pattern[i]))
42 {
43 break;
44 }
45 }
46 }
47 }
48
49 return NULL;
50}
51
52
53#define NODE_MAKER_COND(x) length == 0 || stristr4(x, data)
54#define NODE_MAKER_SHOW(x, y, z) if (NODE_MAKER_COND(y)) {if (ImGui::Button((y + std::string("##SHADERNODEMAKER")).c_str())) { editor->AddNode(new x(handler)); z = z || true; ImGui::CloseCurrentPopup(); } }
55
56
57static bool ShowNodeMaker(NodeEditor *editor, GLSLHandler *handler, ShaderTextureManager *shaderTextureManager, std::vector<DefaultCustomNode> &defaultCustomNodes)
58{
59 static char data[1000];
60 static bool didMake = false;
61 didMake = false;
62 ImGui::InputTextWithHint("##SearchShaderNodes", "Search ...", data, sizeof(data));
63 int length = strlen(data);
64 ImGui::BeginChild("##ShaderNodesMaker", ImVec2(200, 250));
65
66 NODE_MAKER_SHOW(Float3Node, "Float3", didMake);
67
68 NODE_MAKER_SHOW(FloatNode, "Float Value", didMake);
69
70 NODE_MAKER_SHOW(BakeToSlotNode, "Bake To Slot", didMake);
71
72
73 if (NODE_MAKER_COND("Texture"))
74 {
75 if (ImGui::Button(("Texture" + std::string("##SHADERNODEMAKER")).c_str()))
76 {
77 editor->AddNode(new ShaderTextureNode(handler, shaderTextureManager));
78 didMake = didMake || true;
79 ImGui::CloseCurrentPopup();
80 }
81 }
82
83 NODE_MAKER_SHOW(PBRMaterialNode, "PBR Material", didMake);
84
85 for (auto &node : defaultCustomNodes)
86 {
87 if (NODE_MAKER_COND(node.name.data()))
88 {
89 if (ImGui::Button((node.name + std::string("##SHADERNODEMAKER")).c_str()))
90 {
91 editor->AddNode(new CustomShaderNode(handler, node.content));
92 didMake = didMake || true;
93 ImGui::CloseCurrentPopup();
94 }
95 }
96 }
97
98 if (NODE_MAKER_COND("Custom Shader"))
99 {
100 if (ImGui::Button(("Custom Shader" + std::string("##SHADERNODEMAKER")).c_str()))
101 {
102 std::string path = ShowOpenFileDialog("*.json\0");
103
104 if(path.size() > 3)
105 {
106 bool tmp = false;
107 editor->AddNode(new CustomShaderNode(handler, ReadShaderSourceFile(path, &tmp)));
108 didMake = didMake || true;
109 ImGui::CloseCurrentPopup();
110 }
111 }
112 }
113
114 ImGui::EndChild();
115 return didMake;
116}
117
118
119ShadingManager::ShadingManager(ApplicationState *as)
120{
121 appState = as;
122 vsh = new GLSLHandler("Primary Vertex Shader");
123 gsh = new GLSLHandler("Primary Geometry Shader");
124 fsh = new GLSLHandler("Primary Fragment Shader");
125 sharedMemoryManager = new SharedMemoryManager();
126 shaderTextureManager = new ShaderTextureManager();
127 NodeEditorConfig config;
128 config.makeNodeFunc = [&]()
129 {
130 ImGuiNodeEditor::Suspend();
131 ImGui::OpenPopup("NodeMakerDropped");
132 ImGuiNodeEditor::Resume();
133 };
134 config.insNodeFunc = [&](nlohmann::json data) -> NodeEditorNode*
135 {
136 SNENode *node = nullptr;
137
138 if(data["type"] == "ShaderOutput")
139 {
140 node = new ShaderOutputNode(fsh);
141 }
142
143 else if(data["type"] == "Float3")
144 {
145 node = new Float3Node(fsh);
146 }
147
148 else if(data["type"] == "Float")
149 {
150 node = new FloatNode(fsh);
151 }
152
153 else if(data["type"] == "ShaderTexture")
154 {
155 node = new ShaderTextureNode(fsh, shaderTextureManager);
156 }
157
158 else if(data["type"] == "PBRMaterial")
159 {
160 node = new PBRMaterialNode(fsh);
161 }
162
163 else if(data["type"] == "BakeToSlot")
164 {
165 node = new BakeToSlotNode(fsh);
166 }
167
168 else if(data["type"] == "CustomShader")
169 {
170 node = new CustomShaderNode(fsh, data["shader"]);
171 }
172
173 return node;
174 };
175 config.saveFile = GetExecutableDir() + PATH_SEPARATOR "Data" PATH_SEPARATOR "configs" PATH_SEPARATOR "ShaderNodes.json";
176 shaderNodeEditor = new NodeEditor(config);
177 shaderNodeEditor->name = "Shader Nodes";
178 shaderNodeEditor->SetOutputNode(new ShaderOutputNode(fsh));
179 LoadDefaultCustomNodes();
180 ReCompileShaders();
181}
182
183ShadingManager::~ShadingManager()
184{
185 delete vsh;
186 delete gsh;
187 delete fsh;
188 delete sharedMemoryManager;
189}
190
191nlohmann::json ShadingManager::Save()
192{
193 nlohmann::json data;
194 data["nodeEditor"] = shaderNodeEditor->Save();
195 return data;
196}
197
198void ShadingManager::Load(nlohmann::json data)
199{
200 shaderNodeEditor->Load(data["nodeEditor"]);
201 ReCompileShaders();
202}
203
204void ShadingManager::UpdateShaders()
205{
206 // SNENode* outputNode = static_cast<SNENode*>(shaderNodeEditor->outputNode);
207 // outputNode->UpdateShaders();
208 // for(auto& it : shaderNodeEditor->nodes)
209 // {
210 // SNENode* node = static_cast<SNENode*>(it.second);
211 // node->UpdateShaders();
212 // }
213 sharedMemoryManager->UpdateShader(appState->shaders.terrain);
214 shaderTextureManager->Bind(7);
215 appState->shaders.terrain->SetUniformi("_Textures", 7);
216}
217
218void ShadingManager::LoadDefaultCustomNodes()
219{
220 std::string nodesDir = GetExecutableDir() + PATH_SEPARATOR "Data" PATH_SEPARATOR "shader_nodes";
221 defaultCustomNodes.clear();
222 bool tmp = false;
223
224 for (const auto &entry : fs::directory_iterator(nodesDir))
225 {
226 if(entry.path().extension().string() != ".json")
227 continue;
229 n.name = entry.path().filename().string();
230 n.name = n.name.substr(0, n.name.find_last_of("."));
231 n.content = ReadShaderSourceFile(entry.path().string(), &tmp);
232 defaultCustomNodes.push_back(n);
233 }
234
235 extraSource = ReadShaderSourceFile(nodesDir + PATH_SEPARATOR "extras.glsl", &tmp);
236
237}
238
239void ShadingManager::ReCompileShaders()
240{
241 logs.clear();
242 START_PROFILER();
243 sharedMemoryManager->Clear();
244 SNENode *outputNode = static_cast<SNENode *>(shaderNodeEditor->outputNode);
245 outputNode->dataBlobOffset = sharedMemoryManager->AddItem();
246
247 for(auto &it : shaderNodeEditor->nodes)
248 {
249 SNENode *node = static_cast<SNENode *>(it.second);
250 node->dataBlobOffset = sharedMemoryManager->AddItem();
251 }
252
253 outputNode->sharedData = sharedMemoryManager->At(outputNode->dataBlobOffset);
254 outputNode->UpdateShaders();
255
256 for(auto &it : shaderNodeEditor->nodes)
257 {
258 SNENode *node = static_cast<SNENode *>(it.second);
259 node->sharedData = sharedMemoryManager->At(node->dataBlobOffset);
260 node->UpdateShaders();
261 }
262
263 shaderTextureManager->UpdateShaders();
264 PrepVertShader();
265 vertexSource = vsh->GenerateGLSL();
266 PrepGeomShader();
267 geometrySource = gsh->GenerateGLSL();
268 PrepFragShader();
269 fragmentSource = fsh->GenerateGLSL();
270
271 if(optimizeGLSL)
272 {
273 // glslopt_ctx* ctx = glslopt_initialize(glslopt_target::kGlslTargetOpenGL);
274 // glslopt_shader* shader = glslopt_optimize(ctx, glslopt_shader_type::kGlslOptShaderFragment, fragmentSource.data(), 0);
275 // if (glslopt_get_status (shader))
276 // {
277 // fragmentSource = std::string(glslopt_get_output(shader));
278 // }
279 // else
280 // {
281 // logs.push_back(std::string(glslopt_get_log (shader)));
282 // }
283 // glslopt_shader_delete (shader);
284 // glslopt_cleanup (ctx);
285 }
286
287 appState->shaders.terrain = new Shader(vertexSource, fragmentSource, geometrySource);
288 double time = 0.0f;
289 END_PROFILER(time);
290 logs.push_back("Generated & Compiled Shaders in " + std::to_string(time) + "ms");
291}
292
293void ShadingManager::ShowSettings(bool *pOpen)
294{
295 ImGui::Begin("Shading##ShadingManager", pOpen);
296
297 if(ImGui::Button("Compile Shaders"))
298 {
299 ReCompileShaders();
300 }
301
302 ImGui::SameLine();
303
304 if(ImGui::Button("Export GLSL"))
305 {
306 std::string path = ShowSaveFileDialog("*.glsl\0");
307
308 if(path.size() > 3)
309 {
310 SaveToFile(path, fragmentSource);
311 }
312 }
313
314 if(ImGui::Button("Print GLSL"))
315 {
316 std::cout << fragmentSource << std::endl;
317 }
318
319 ImGui::SameLine();
320
321 ImGui::SameLine();
322
323 if(ImGui::Checkbox("Optimize GLSL", &optimizeGLSL))
324 {
325 ReCompileShaders();
326 }
327
328 //ImGui::Text("SMM Size : %d", sharedMemoryManager->sharedMemoryBlobs.size());
329 //ImGui::Text("SMM : %f, %f, %f", sharedMemoryManager->sharedMemoryBlobs[0].d0, sharedMemoryManager->sharedMemoryBlobs[0].d1, sharedMemoryManager->sharedMemoryBlobs[0].d2);
330
331 if(ImGui::CollapsingHeader("Logs"))
332 {
333 if(logs.size() > 0)
334 {
335 ImGui::Text("Logs:");
336
337 for(std::string &s : logs)
338 {
339 ImGui::Text(s.data());
340 }
341 }
342 }
343
344 if(ImGui::CollapsingHeader("Shader Nodes"))
345 {
346 if (ImGui::Button("Add Node##ShaderNodeMaker"))
347 {
348 ImGui::OpenPopup("NodeMakerDropped");
349 }
350
351 ImGui::SameLine();
352
353 if (ImGui::Button("Reset##ShaderNodeMaker"))
354 {
355 shaderNodeEditor->Reset();
356 ReCompileShaders();
357 }
358
359 ImGui::SameLine();
360
361 if (ImGui::Button("Export##ShaderNodeMaker"))
362 {
363 std::string file = ShowSaveFileDialog("*.terr3d");
364
365 if (file.size() > 3)
366 {
367 if (file.find(".terr3d") == std::string::npos)
368 {
369 file += ".terr3d";
370 }
371
372 SaveToFile(file, shaderNodeEditor->Save().dump(4));
373 }
374 }
375
376 ImGui::SameLine();
377
378 if (ImGui::Button("Import##CPUNE"))
379 {
380 std::string file = ShowOpenFileDialog("*.terr3d");
381
382 if (file.size() > 3)
383 {
384 bool tmp = false;
385 shaderNodeEditor->Reset();
386 shaderNodeEditor->Load(nlohmann::json::parse(ReadShaderSourceFile(file, &tmp)));
387 ReCompileShaders();
388 }
389 }
390
391 ImGui::SameLine();
392
393 if(ImGui::Button("Reload Nodes"))
394 {
395 LoadDefaultCustomNodes();
396 }
397
398 int nC = shaderNodeEditor->nodes.size();
399 int lC = shaderNodeEditor->links.size();
400 int pC = shaderNodeEditor->pins.size();
401 shaderNodeEditor->Render();
402
403 if ((nC != shaderNodeEditor->nodes.size()) || (lC != shaderNodeEditor->links.size()) || (pC != shaderNodeEditor->pins.size()))
404 {
405 ReCompileShaders();
406 }
407 }
408
409 if (ImGui::IsWindowFocused() && (((IsKeyDown(TERR3D_KEY_RIGHT_SHIFT) || IsKeyDown(TERR3D_KEY_LEFT_SHIFT)) && IsKeyDown(TERR3D_KEY_A)) || IsMouseButtonDown(TERR3D_MOUSE_BUTTON_MIDDLE)))
410 {
411 ImGui::OpenPopup("NodeMakerDropped");
412 }
413
414 if(ImGui::BeginPopup("NodeMakerDropped"))
415 {
416 if(ShowNodeMaker(shaderNodeEditor, fsh, shaderTextureManager, defaultCustomNodes))
417 {
418 ReCompileShaders();
419 }
420
421 if (ImGui::Button("Close##ShaderNodeMaker"))
422 {
423 ImGui::CloseCurrentPopup();
424 }
425
426 ImGui::EndPopup();
427 }
428
429 ImGui::End();
430}
431
432void ShadingManager::PrepVertShader()
433{
434 vsh->Clear();
435 vsh->AddTopLine(GLSLLine("layout (location = 0) in vec4 aPos;", "The world position of the vertex"));
436 vsh->AddTopLine(GLSLLine("layout (location = 1) in vec4 aNorm;", "The vertex normals"));
437 vsh->AddTopLine(GLSLLine("layout (location = 2) in vec2 aTexCoord;", "The texture coordinates of the vertex"));
438 vsh->AddTopLine(GLSLLine("layout (location = 3) in vec4 aExtras1;", "Extra data like generated height, erosion delta, etc."));
439 vsh->AddTopLine(GLSLLine("", "The Output passed to the Geometry Shader"));
440 vsh->AddTopLine(GLSLLine(R"(
441out DATA
442{
443 float height;
444 vec3 FragPos;
445 vec3 Normal;
446 vec2 TexCoord;
447 vec4 Extras1;
448} data_out;
449)"));
450
451 vsh->AddUniform(GLSLUniform("_Model", "mat4"));
452 vsh->AddUniform(GLSLUniform("_PV", "mat4"));
453 vsh->AddUniform(GLSLUniform("_TextureBake", "float", "0.0f"));
454 vsh->AddUniform(GLSLUniform("_Scale", "float", "1.0f"));
455 vsh->AddUniform(GLSLUniform("_Tiled", "float", "0.0f"));
456 vsh->AddUniform(GLSLUniform("_NumTiles", "float", "0.0f"));
457 vsh->AddUniform(GLSLUniform("_TileX", "float", "0.0f"));
458 vsh->AddUniform(GLSLUniform("_TileY", "float", "0.0f"));
459
460 GLSLFunction main("main");
461 main.AddLine(GLSLLine("", "TEMP"));
462 main.AddLine(GLSLLine(R"(
463
464if(_TextureBake == 0.0f)
465 gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);
466else
467{
468 if(_Tiled == 0.0f)
469 {
470 gl_Position = vec4(aPos.x/_Scale, aPos.z/_Scale, 0.0f, 1.0f);
471 }
472 else
473 {
474 float factor = _NumTiles / _Scale;
475 gl_Position = vec4(aPos.x * factor + _TileX, aPos.z * factor + _TileY, 0.0f, 1.0f);
476 }
477}
478)"));
479 main.AddLine(GLSLLine("data_out.height = aExtras1.x;", "The actual generated noise value"));
480 main.AddLine(GLSLLine("data_out.FragPos = vec3(aPos.x, aPos.y, aPos.z);", "The world position"));
481 main.AddLine(GLSLLine("data_out.Normal = vec3(aNorm.x, aNorm.y, aNorm.z);", "The vertex normals"));
482 main.AddLine(GLSLLine("data_out.TexCoord = aTexCoord;", "The texture coordinates"));
483 main.AddLine(GLSLLine("data_out.Extras1 = aExtras1;", "The texture coordinates"));
484
485
486 vsh->AddFunction(main);
487}
488
489void ShadingManager::PrepGeomShader()
490{
491 gsh->Clear();
492
493 gsh->AddTopLine(GLSLLine("layout(triangles) in;", "Take 3 vertices of a triangles as input"));
494 gsh->AddTopLine(GLSLLine("layout(triangle_strip, max_vertices = 3) out;"));
495 gsh->AddTopLine(GLSLLine("", "The data passed in from the vertex shader"));
496 gsh->AddTopLine(GLSLLine(R"(
497in DATA
498{
499 float height;
500 vec3 FragPos;
501 vec3 Normal;
502 vec2 TexCoord;
503 vec4 Extras1;
504} data_in[];
505)"));
506 gsh->AddTopLine(GLSLLine(""));
507 gsh->AddTopLine(GLSLLine("out float height;", "Pass the height to the fragment shader"));
508 gsh->AddTopLine(GLSLLine("out vec4 FragPos;", "Pass the position to the fragment shader"));
509 gsh->AddTopLine(GLSLLine("out vec4 Extras1;", "Pass the extras to the fragment shader"));
510 gsh->AddTopLine(GLSLLine("out vec3 Normal;", "Pass the normal to the fragment shader"));
511 gsh->AddTopLine(GLSLLine("out vec2 TexCoord;", "Pass the texture coordinates to the fragment shader"));
512 gsh->AddTopLine(GLSLLine("out mat3 TBN;", "Pass the Tangent Bitangent Normal matrix to the fragment shader"));
513
514 gsh->AddUniform(GLSLUniform("_PV", "mat4"));
515 gsh->AddUniform(GLSLUniform("_FlatShade", "float"));
516
517 GLSLFunction main("main");
518 main.AddLine(GLSLLine("vec3 a = (_PV * gl_in[0].gl_Position).xyz;", "Vertex a of triangle"));
519 main.AddLine(GLSLLine("vec3 b = (_PV * gl_in[1].gl_Position).xyz;", "Vertex b of triangle"));
520 main.AddLine(GLSLLine("vec3 c = (_PV * gl_in[2].gl_Position).xyz;", "Vertex c of triangle"));
521 main.AddLine(GLSLLine(""));
522 main.AddLine(GLSLLine("vec3 edge0 = b - c;"));
523 main.AddLine(GLSLLine("vec3 edge1 = c - a;"));
524 main.AddLine(GLSLLine(""));
525 main.AddLine(GLSLLine("vec2 deltaUV0 = data_in[1].TexCoord - data_in[0].TexCoord;"));
526 main.AddLine(GLSLLine("vec2 deltaUV1 = data_in[2].TexCoord - data_in[0].TexCoord;"));
527 main.AddLine(GLSLLine(""));
528 main.AddLine(GLSLLine("float invDet = 1.0f / (deltaUV0.x * deltaUV1.y - deltaUV1.x * deltaUV0.y);", "One over the determinant"));
529 main.AddLine(GLSLLine(""));
530 main.AddLine(GLSLLine("vec3 tangent = vec3(invDet * (deltaUV1.y * edge0 - deltaUV0.y * edge1));"));
531 main.AddLine(GLSLLine("vec3 bitangent = vec3(invDet * (-deltaUV1.x * edge0 + deltaUV0.x * edge1));"));
532 main.AddLine(GLSLLine("mat4 model = mat4(1);", "A default model matrix"));
533 main.AddLine(GLSLLine(""));
534 main.AddLine(GLSLLine("vec3 T = normalize(vec3(model * vec4(tangent, 0.0f)));"));
535 main.AddLine(GLSLLine("vec3 B = normalize(vec3(model * vec4(bitangent, 0.0f)));"));
536 main.AddLine(GLSLLine("vec3 N = normalize(vec3(model * vec4(cross(edge1, edge0), 0.0f)));"));
537 main.AddLine(GLSLLine(""));
538 main.AddLine(GLSLLine("TBN = mat3(T, B, N);"));
539 main.AddLine(GLSLLine(""));
540 main.AddLine(GLSLLine("vec3 n = normalize(cross(edge1, edge0));", "Calculate face normal for flat shading"));
541 main.AddLine(GLSLLine(""));
542
543 for(int i=0;i<3;i++)
544 {
545 main.AddLine(GLSLLine("gl_Position = _PV * gl_in[" + std::to_string(i) + "].gl_Position;"));
546 main.AddLine(GLSLLine("height = data_in[" + std::to_string(i) + "].height;"));
547 main.AddLine(GLSLLine("TexCoord = data_in[" + std::to_string(i) + "].TexCoord;"));
548 main.AddLine(GLSLLine("Extras1 = data_in[" + std::to_string(i) + "].Extras1;"));
549 main.AddLine(GLSLLine("FragPos = vec4(data_in[" + std::to_string(i) + "].FragPos, 1.0f);"));
550 main.AddLine(GLSLLine(R"(
551 if(_FlatShade > 0.5f)
552 Normal = n;
553 else
554 Normal = data_in[)" + std::to_string(i) + R"(].Normal;
555 )"));
556 main.AddLine(GLSLLine("EmitVertex();", "Emit the vertex"));
557}
558
559main.AddLine(GLSLLine("EndPrimitive();", "Emit the triangle"));
560
561
562gsh->AddFunction(main);
563
564}
565
566void ShadingManager::PrepFragShader()
567{
568 fsh->Clear();
569 fsh->AddTopLine(GLSLLine("out vec4 FragColor;", "The result of the fragment shader"));
570 fsh->AddTopLine(GLSLLine(""));
571 fsh->AddTopLine(GLSLLine("in float height;", "Take the height passed in from the Geometry Shader"));
572 fsh->AddTopLine(GLSLLine("in vec4 FragPos;", "Take the world position passed in from the Geometry Shader"));
573 fsh->AddTopLine(GLSLLine("in vec4 Extras1;", "Take the extras 1 passed in from the Geometry Shader"));
574 fsh->AddTopLine(GLSLLine("in vec3 Normal;", "Take the normal passed in from the Geometry Shader"));
575 fsh->AddTopLine(GLSLLine("in vec2 TexCoord;", "Take the texture coordinates passed in from the Geometry Shader"));
576 fsh->AddTopLine(GLSLLine("in mat3 TBN;", "Take the tangent bitangent normal matrix in from the Geometry Shader"));
577 fsh->AddTopLine(GLSLLine(""));
578 fsh->AddTopLine(GLSLLine(extraSource));
579 fsh->AddTopLine(GLSLLine(""));
580 fsh->AddTopLine(GLSLLine(R"(
581 struct DataBlob
582 {
583 float d[32];
584 };
585 )"));
586 fsh->AddTopLine(GLSLLine("const float PI = 3.14159265359;"));
587 fsh->AddTopLine(GLSLLine("const float gamma = 2.2f;"));
588 fsh->AddUniform(GLSLUniform("_LightPosition", "vec3"));
589 fsh->AddUniform(GLSLUniform("_LightColor", "vec3"));
590 fsh->AddUniform(GLSLUniform("_LightStrength", "float"));
591 fsh->AddUniform(GLSLUniform("_CameraPos", "vec3"));
592 fsh->AddUniform(GLSLUniform("_HMapMinMax", "vec3"));
593 fsh->AddUniform(GLSLUniform("_TextureBake", "float", "0.0f"));
594 fsh->AddUniform(GLSLUniform("_Slot", "float", "0.0f"));
595 fsh->AddUniform(GLSLUniform("_Tiled", "float", "0.0f"));
596 fsh->AddUniform(GLSLUniform("_NumTiles", "float", "0.0f"));
597 fsh->AddUniform(GLSLUniform("_TileX", "float", "0.0f"));
598 fsh->AddUniform(GLSLUniform("_TileY", "float", "0.0f"));
599 fsh->AddUniform(GLSLUniform("_Textures", "sampler2DArray"));
600 GLSLSSBO dataBlobs("dataBlobs", std::to_string(sharedMemoryManager->ssboBinding), "These are small data blobs which may be used for nodes, etc.");
601 dataBlobs.AddLine(GLSLLine("DataBlob data[];"));
602 fsh->AddSSBO(dataBlobs);
603 GLSLFunction main("main");
604 main.AddLine(GLSLLine(""));
605 main.AddLine(GLSLLine("vec3 textureBakeSlots[10];"));
606 GLSLLine tmp("", "");
607 NodeInputParam param;
608 param.userData1 = &main;
609 param.userData2 = &tmp;
610 shaderNodeEditor->outputNode->Evaluate(param, nullptr);
611 main.AddLine(GLSLLine(""));
612 main.AddLine(GLSLLine(R"(
613 if(_TextureBake == 1.0f)
614 {
615 textureBakeSlots[0] = vec3( (height - _HMapMinMax.x) / (_HMapMinMax.y - _HMapMinMax.x) ); // Slot 0 is reserved for height map
616 FragColor = vec4(textureBakeSlots[int(_Slot)], 1.0f);
617 return;
618 }
619 )"));
620 main.AddLine(GLSLLine(""));
621 main.AddLine(GLSLLine("FragColor = vec4(" + tmp.line + ", 1.0f);"));
622 fsh->AddFunction(main);
623}
624
Definition: Shader.h:7
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json parse(InputType &&i, const parser_callback_t cb=nullptr, const bool allow_exceptions=true, const bool ignore_comments=false)
deserialize from a compatible input
Definition: json.hpp:24605
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition: json.hpp:20117
a class to store JSON values
Definition: json.hpp:17860