1#include "ShaderBuilder.h"
3#include "Utilities/Strings.h"
4#include "Utilities/Preprocessor.h"
5#include "ResourceStore.h"
6#include "Renderer/EnginePermutations.h"
8#include "Rendering/IGraphicsDevice.h"
10#include "Foundation/Logging/Logger.h"
11#include "Foundation/StringUtilities.h"
12#include "Foundation/StringView.h"
21 constexpr size_t InitialBufferCapasity = 4096u;
26 } engineTextures[] = {
27 { Strings::add(
"environmentSky"), Strings::add(
"ENVIRONMENT_SKY")},
28 { Strings::add(
"environmentRadiance"), Strings::add(
"ENVIRONMENT_RADIANCE")},
29 { Strings::add(
"environmentIrradiance"), Strings::add(
"ENVIRONMENT_IRRADIANCE")},
30 { Strings::add(
"ambientIrradiance"), Strings::add(
"AMBIENT_IRRADIANCE")},
31 { Strings::add(
"brdfLUT"), Strings::add(
"BRDF_LUT")},
32 { Strings::add(
"cascadedShadowMap"), Strings::add(
"CASCADEDSHADOWMAP")},
33 { Strings::add(
"cubeShadowMap"), Strings::add(
"CUBESHADOWMAP")}
36 struct EngineBufferMember
44 Strings::add(
"projectionMatrix"),
45 Strings::add(
"viewMatrix"),
46 Strings::add(
"inverseViewMatrix"),
47 Strings::add(
"inverseProjectionMatrix"),
48 Strings::add(
"worldToClipMatrix"),
49 Strings::add(
"projectionParameters"),
50 Strings::add(
"clippingPlanes"),
51 Strings::add(
"blueNoiseOffset"),
52 Strings::add(
"viewportOrigin"),
53 Strings::add(
"viewportSize"),
54 Strings::add(
"viewportSizeRcp"),
55 Strings::add(
"shadowDepthClamp"),
56 Strings::add(
"animationTime"),
57 Strings::add(
"exposure"),
58 Strings::add(
"sceneFlags"),
59 Strings::add(
"clientFlags"),
60 Strings::add(
"environmentRadianceMips"),
61 Strings::add(
"environmentIrradianceMips")
65 Strings::add(
"getClipFromViewMatrix"),
66 Strings::add(
"getClipFromWorldMatrix"),
67 Strings::add(
"getViewFromWorldMatrix"),
68 Strings::add(
"getViewFromClipMatrix"),
69 Strings::add(
"getWorldFromViewMatrix"),
70 Strings::add(
"getViewFromViewportMatrix")
74 Strings::add(
"worldMatrix"),
75 Strings::add(
"objectId")
79 Strings::add(
"boneTransforms")
83 Strings::add(
"lightPositions"),
84 Strings::add(
"lightDirections"),
85 Strings::add(
"lightColorIntensity"),
86 Strings::add(
"lightParameters"),
87 Strings::add(
"numLights"),
88 Strings::add(
"eyePosition"),
89 Strings::add(
"fogColor"),
90 Strings::add(
"fogDistance"),
91 Strings::add(
"fogAmount"),
92 Strings::add(
"fogEnabled"),
93 Strings::add(
"ambientIntensity"),
94 Strings::add(
"ambientColor"),
95 Strings::add(
"environmentBrightness"),
96 Strings::add(
"skyMultiplier"),
97 Strings::add(
"seaFlags"),
102 Strings::add(
"shadows"),
103 Strings::add(
"cascadeOffsets")
106 struct EngineBuffer {
110 } engineBuffers[] = {
111 { sceneBufferMembers,
sizeof(sceneBufferMembers) /
sizeof(sceneBufferMembers[0]), Strings::add(
"SCENEBUFFER") },
112 { viewGetters,
sizeof(viewGetters) /
sizeof(viewGetters[0]), Strings::add(
"VIEWGETTERS") },
113 { objectBufferMembers,
sizeof(objectBufferMembers) /
sizeof(objectBufferMembers[0]), Strings::add(
"OBJECTBUFFER") },
114 { animationBufferMembers,
sizeof(animationBufferMembers) /
sizeof(animationBufferMembers[0]), Strings::add(
"ANIMATIONBUFFER") },
115 { lightBufferMembers,
sizeof(lightBufferMembers) /
sizeof(lightBufferMembers[0]), Strings::add(
"LIGHTBUFFER") },
116 { shadowBufferMembers,
sizeof(shadowBufferMembers) /
sizeof(shadowBufferMembers[0]), Strings::add(
"SHADOWBUFFER") }
123 content.append(
"#include \"");
125 content.append(path.to_string_view());
126 content.append(
"\"\n");
129 void changeSuffix(std::string& dst,
const std::string_view& from,
const std::string_view& to)
131 auto pos = dst.find(from);
132 if (pos == std::string::npos)
return;
133 dst.replace(pos, to.length(), to);
136 void addEffectDefinesAndStuff(std::string& output,
137 const std::vector<std::pair<std::string, std::string>>& definitions,
138 uint32_t multiViewCount,
bool isVertexShader)
140 output.append(
"#version 300 es\n");
141 if (multiViewCount) {
142 std::string multiViewCountString = std::to_string(multiViewCount);
143 if (isVertexShader) {
144 output.append(
"#extension GL_OVR_multiview : require\nlayout(num_views=");
145 output.append(multiViewCountString);
146 output.append(
") in;\n");
148 output.append(
"#define COGS_MULTIVIEW ");
149 output.append(multiViewCountString);
152 output.append(
"precision highp float;\n"
153 "precision highp int;\n"
154 "precision highp sampler2DArrayShadow;\n"
155 "precision highp samplerCubeShadow;\n"
156 "precision mediump sampler2DArray;\n"
157 "precision highp isampler2D;\n"
158 "precision highp usampler2D;\n"
159 "precision highp usampler2DArray;\n"
160 "precision highp isampler2DArray;\n"
161 "layout (std140) uniform;\n");
162 for (
const std::pair<std::string,std::string>& define : definitions) {
163 output.append(
"#define ");
164 output.append(define.first);
166 output.append(define.second);
171 [[nodiscard]] std::string_view attributeVaryingType(
const MaterialDataType type)
174 case MaterialDataType::Float:
return "float ";
break;
175 case MaterialDataType::Float2:
return "vec2 ";
break;
176 case MaterialDataType::Float3:
return "vec3 ";
break;
177 case MaterialDataType::Float4:
return "vec4 ";
break;
178 case MaterialDataType::Float4x4:
return "mat4 ";
break;
179 case MaterialDataType::Int:
return "int ";
break;
180 case MaterialDataType::Int2:
return "ivec4 ";
break;
181 case MaterialDataType::Int3:
return "ivec3 ";
break;
182 case MaterialDataType::Int4:
return "ivec4 ";
break;
183 case MaterialDataType::UInt:
return "uint ";
break;
184 case MaterialDataType::UInt2:
return "uvec4 ";
break;
185 case MaterialDataType::UInt3:
return "uvec3 ";
break;
186 case MaterialDataType::UInt4:
return "uvec4 ";
break;
187 case MaterialDataType::SV_IsFrontFace:
return "bool ";
break;
188 case MaterialDataType::VFACE:
return "float ";
break;
189 case MaterialDataType::Position:
return "vec4 ";
break;
191 LOG_ERROR(logger,
"Unsupported attribute type %d",
int(type));
197 const char* semanticNames[]
207 static_assert(
sizeof(semanticNames) ==
sizeof(semanticNames[0]) * (size_t(ShaderInterfaceMemberDefinition::SemanticName::FirstSystemValueSemantic) - 1));
213 if ((attribute.semantic.name != ShaderInterfaceMemberDefinition::SemanticName::None)
214 && (
size_t(attribute.semantic.name) <
size_t(ShaderInterfaceMemberDefinition::SemanticName::FirstSystemValueSemantic)))
216 shaderSource.append(
"in ");
217 shaderSource.append(attributeVaryingType(attribute.type));
218 shaderSource.append(semanticNames[
size_t(attribute.semantic.name) - 1]);
219 shaderSource.append(std::to_string(attribute.semantic.slot));
220 shaderSource.append(
";\n");
223 switch (attribute.semantic.name) {
224 case ShaderInterfaceMemberDefinition::SemanticName::SV_VertexID: [[fallthrough]];
225 case ShaderInterfaceMemberDefinition::SemanticName::SV_InstanceID:
228 LOG_WARNING(logger,
"Unexpected semantic name '%.*s'",
229 StringViewFormat(ShaderInterfaceMemberDefinition::semanticNameString(attribute.semantic.name)));
233 shaderSource.append(
"\n");
238 shaderSource.append(
"struct ");
239 shaderSource.append(name);
240 shaderSource.append(
" {\n");
241 for (
const auto& attribute : iface.members) {
242 shaderSource.append(
" ");
243 shaderSource.append(attributeVaryingType(attribute.type));
244 shaderSource.append(attribute.name);
245 shaderSource.append(
";\n");
247 shaderSource.append(
"};\n\n");
250 void addAttributeImportFunc(std::string& shaderSource,
const std::string_view& name,
const ShaderInterfaceDefinition& iface)
252 shaderSource.append(name);
253 shaderSource.append(
" importAttributes() {\n");
254 shaderSource.append(
" ");
255 shaderSource.append(name);
256 shaderSource.append(
" t;\n");
257 for (
const auto& attribute : iface.members) {
260 if ((attribute.semantic.name != ShaderInterfaceMemberDefinition::SemanticName::None)
261 && (
size_t(attribute.semantic.name) <
size_t(ShaderInterfaceMemberDefinition::SemanticName::FirstSystemValueSemantic)))
263 shaderSource.append(
" t.");
264 shaderSource.append(attribute.name);
265 shaderSource.append(
" = ");
266 shaderSource.append(semanticNames[
size_t(attribute.semantic.name) - 1]);
267 shaderSource.append(std::to_string(attribute.semantic.slot));
268 shaderSource.append(
";\n");
271 switch (attribute.semantic.name) {
272 case ShaderInterfaceMemberDefinition::SemanticName::SV_VertexID:
273 shaderSource.append(
" t.");
274 shaderSource.append(attribute.name);
275 shaderSource.append(
" = ");
276 shaderSource.append(attributeVaryingType(attribute.type));
277 shaderSource.append(
"(gl_VertexID);\n");
279 case ShaderInterfaceMemberDefinition::SemanticName::SV_InstanceID:
280 shaderSource.append(
" t.");
281 shaderSource.append(attribute.name);
282 shaderSource.append(
" = ");
283 shaderSource.append(attributeVaryingType(attribute.type));
284 shaderSource.append(
"(gl_InstanceID);\n");
291 shaderSource.append(
" return t;\n}\n\n");
294 void addInOutVariables(std::string& shaderSource,
const std::string_view& prefix,
const ShaderInterfaceDefinition& iface,
bool in)
296 if (iface.members.empty())
return;
297 for (
const auto& out : iface.members) {
299 case MaterialDataType::SV_IsFrontFace:
300 case MaterialDataType::VFACE:
304 if (out.modifiers & ShaderInterfaceMemberDefinition::CentroidModifier) {
305 shaderSource.append(
"centroid ");
307 if (out.modifiers & ShaderInterfaceMemberDefinition::NointerpolationModifier) {
308 shaderSource.append(
"flat ");
310 shaderSource.append(in ?
"in " :
"out ");
311 shaderSource.append(attributeVaryingType(out.type));
312 shaderSource.append(prefix);
313 shaderSource.append(out.name);
314 shaderSource.append(
";\n");
318 shaderSource.append(
"\n");
321 void addInterfaceConstructor(std::string& shaderSource,
const std::string_view& name,
const ShaderInterfaceDefinition& iface)
323 shaderSource.append(name);
324 shaderSource.append(
" create");
325 shaderSource.append(name);
326 shaderSource.append(
"() {\n");
327 shaderSource.append(
" ");
328 shaderSource.append(name);
329 shaderSource.append(
" t;\n");
330 for (
const auto& attribute : iface.members) {
331 const char* initializer =
nullptr;
332 switch (attribute.type) {
333 case MaterialDataType::Float: initializer =
"0.0;\n";
break;
334 case MaterialDataType::Float2: initializer =
"vec2(0);\n";
break;
335 case MaterialDataType::Float3: initializer =
"vec3(0);\n";
break;
336 case MaterialDataType::Float4: initializer =
"vec4(0);\n";
break;
337 case MaterialDataType::Float4x4: initializer =
"mat4(0);\n";
break;
342 shaderSource.append(
" t.");
343 shaderSource.append(attribute.name);
344 shaderSource.append(
" = ");
345 shaderSource.append(initializer);
348 shaderSource.append(
" return t;\n}\n\n");
353 shaderSource.append(
"void exportOut(");
354 shaderSource.append(name);
355 shaderSource.append(
" vertexOut) {\n");
356 for (
const auto& attribute : iface.members) {
357 switch (attribute.type) {
358 case MaterialDataType::SV_IsFrontFace:
359 case MaterialDataType::VFACE:
363 shaderSource.append(
" vsfs_");
364 shaderSource.append(attribute.name);
365 shaderSource.append(
" = vertexOut.");
366 shaderSource.append(attribute.name);
367 shaderSource.append(
";\n");
371 shaderSource.append(
"}\n");
376 shaderSource.append(name);
377 shaderSource.append(
" importIn() {\n ");
378 shaderSource.append(name);
379 shaderSource.append(
" t;\n");
380 for (
const auto& attribute : iface.members) {
381 switch (attribute.type) {
382 case MaterialDataType::SV_IsFrontFace:
383 shaderSource.append(
" t.");
384 shaderSource.append(attribute.name);
385 shaderSource.append(
" = gl_FrontFacing;\n");
387 case MaterialDataType::VFACE:
388 shaderSource.append(
" t.");
389 shaderSource.append(attribute.name);
390 shaderSource.append(
" = gl_FrontFacing ? 1.0 : -1.0;\n");
392 case MaterialDataType::Position:
393 shaderSource.append(
" t.");
394 shaderSource.append(attribute.name);
395 shaderSource.append(
" = gl_FragCoord;\n");
398 shaderSource.append(
" t.");
399 shaderSource.append(attribute.name);
400 shaderSource.append(
" = vsfs_");
401 shaderSource.append(attribute.name);
402 shaderSource.append(
";\n");
406 shaderSource.append(
" return t;\n}\n");
411 shaderSource.append(
"void transferAttributes(in VertexIn vertexIn, inout VertexOut vertexOut) {\n");
413 if (member.semantic.name == ShaderInterfaceMemberDefinition::SemanticName::SV_VertexID)
continue;
415 if (dMember.name == member.name) {
416 shaderSource.append(
" vertexOut.");
417 shaderSource.append(member.name);
418 shaderSource.append(
" = ");
419 if (dMember.type == MaterialDataType::Float3 && member.type == MaterialDataType::Float2 && member.semantic.name == ShaderInterfaceMemberDefinition::SemanticName::Normal) {
420 shaderSource.append(
"octDecode(vertexIn.");
421 shaderSource.append(member.name);
422 shaderSource.append(
"); \n");
425 if (dMember.type == MaterialDataType::Float4 && member.type == MaterialDataType::Float3) {
426 shaderSource.append(
"vec4(vertexIn.");
427 shaderSource.append(member.name);
428 shaderSource.append(
", 1.0);\n");
431 if (dMember.type == MaterialDataType::Float4 && member.type == MaterialDataType::Float2) {
432 shaderSource.append(
"vec4(vertexIn.");
433 shaderSource.append(member.name);
434 shaderSource.append(
", 0.0, 1.0);\n");
438 if (dMember.type != member.type) {
439 switch (dMember.type) {
440 case MaterialDataType::Float: shaderSource.append(
"float("); close =
true;
break;
441 case MaterialDataType::Float2: shaderSource.append(
"vec2("); close =
true;
break;
442 case MaterialDataType::Float3: shaderSource.append(
"vec3("); close =
true;
break;
443 case MaterialDataType::Float4: shaderSource.append(
"vec4("); close =
true;
break;
444 case MaterialDataType::Float4x4: shaderSource.append(
"mat4("); close =
true;
break;
445 case MaterialDataType::Int: shaderSource.append(
"int("); close =
true;
break;
446 case MaterialDataType::Int2: shaderSource.append(
"ivec2("); close =
true;
break;
447 case MaterialDataType::Int3: shaderSource.append(
"ivec3("); close =
true;
break;
448 case MaterialDataType::Int4: shaderSource.append(
"ivec4("); close =
true;
break;
449 case MaterialDataType::UInt: shaderSource.append(
"uint("); close =
true;
break;
450 case MaterialDataType::UInt2: shaderSource.append(
"uvec2("); close =
true;
break;
451 case MaterialDataType::UInt3: shaderSource.append(
"uvec3("); close =
true;
break;
452 case MaterialDataType::UInt4: shaderSource.append(
"uvec4("); close =
true;
break;
457 shaderSource.append(
"vertexIn.");
458 shaderSource.append(member.name);
459 if (close) shaderSource.append(1,
')');
460 shaderSource.append(
";\n");
465 shaderSource.append(
"}\n");
469 void addEngineUniformBuffer(std::string& shaderSource,
const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen)
471 for (
const EngineBuffer& engineBuffer : engineBuffers) {
474 bool referenced =
false;
475 for (
size_t i = 0; i < engineBuffer.count; i++) {
476 if (identifiersSeen.contains(engineBuffer.members[i])) {
485 shaderSource.append(
"#define COGS_");
486 shaderSource.append(Strings::get(engineBuffer.name).to_string_view());
487 shaderSource.append(
"_REFERENCED 1\n");
492 void addUniformBuffer(std::string& shaderSource,
493 const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen,
496 if (definition.values.empty())
return;
499 bool isInUse =
false;
501 if (identifiersSeen.contains(Strings::add(member.name))) {
506 if (!isInUse)
return;
509 shaderSource.append(
"uniform ");
510 shaderSource.append(definition.name);
511 shaderSource.append(
" {\n");
513 shaderSource.append(2,
' ');
514 switch (member.type) {
515 case MaterialDataType::Float: shaderSource.append(
"float");
break;
516 case MaterialDataType::Float2: shaderSource.append(
"vec2");
break;
517 case MaterialDataType::Float3: shaderSource.append(
"vec3");
break;
518 case MaterialDataType::Float4: shaderSource.append(
"vec4");
break;
519 case MaterialDataType::Float4x4: shaderSource.append(
"mat4");
break;
520 case MaterialDataType::Float4Array: shaderSource.append(
"vec4");
break;
521 case MaterialDataType::Float4x4Array: shaderSource.append(
"mat4");
break;
522 case MaterialDataType::Int: shaderSource.append(
"int");
break;
523 case MaterialDataType::Int2: shaderSource.append(
"ivec2");
break;
524 case MaterialDataType::Int3: shaderSource.append(
"ivec3");
break;
525 case MaterialDataType::Int4: shaderSource.append(
"ivec4");
break;
526 case MaterialDataType::UInt: shaderSource.append(
"uint");
break;
527 case MaterialDataType::UInt2: shaderSource.append(
"uvec2");
break;
528 case MaterialDataType::UInt3: shaderSource.append(
"uvec3");
break;
529 case MaterialDataType::UInt4: shaderSource.append(
"uvec4");
break;
530 case MaterialDataType::Bool: shaderSource.append(
"bool");
break;
532 shaderSource.append(
"<invalid type>");
535 shaderSource.append(1,
' ');
536 shaderSource.append(member.name);
537 if (member.type == MaterialDataType::Float4Array || member.type == MaterialDataType::Float4x4Array) {
538 assert(member.dimension !=
static_cast<size_t>(-1));
539 shaderSource.append(
"[");
540 shaderSource.append(std::to_string(member.dimension));
541 shaderSource.append(
"]");
543 shaderSource.append(
";\n");
545 shaderSource.append(
"};\n");
549 void addEngineUniforms(std::string& shaderSource,
const std::unordered_set<StringRef>& identifiersSeen)
551 for (
auto& item : engineUniforms) {
552 bool active = identifiersSeen.count(item.name);
553 for (
auto dependee : item.dependees) {
554 active = active || identifiersSeen.count(dependee);
557 shaderSource.append(
"uniform ");
559 case MaterialDataType::Float4:
560 shaderSource.append(
"vec4 ");
562 case MaterialDataType::Float4x4:
563 shaderSource.append(
"mat4 ");
566 assert(
false &&
"Unhandled material data type");
568 auto name = Strings::get(item.name);
569 shaderSource.append(name.to_string_view());
570 shaderSource.append(
";\n");
573 if (identifiersSeen.count(objectId)) shaderSource.append(
"float objectId() { return objectData.x; }\n");
574 if (identifiersSeen.count(animationTime)) shaderSource.append(
"float animationTime() { return objectData.y; }\n");
575 if (identifiersSeen.count(environmentRadianceMips)) shaderSource.append(
"float environmentRadianceMips() { return environmentInfo.x; }\n");
576 if (identifiersSeen.count(environmentIrradianceMips)) shaderSource.append(
"float environmentIrradianceMips() { return environmentInfo.y; }\n");
577 if (identifiersSeen.count(exposure)) shaderSource.append(
"float exposure() { return environmentInfo.z; }\n");
578 if (identifiersSeen.count(environmentBrightness)) shaderSource.append(
"float environmentBrightness() { return environmentInfo.w; }\n");
585 shaderSource.append(
"uniform ");
588 case MaterialTypePrecision::Default:
590 case MaterialTypePrecision::Low:
591 shaderSource.append(
"lowp ");
593 case MaterialTypePrecision::Medium:
594 shaderSource.append(
"mediump ");
596 case MaterialTypePrecision::High:
597 shaderSource.append(
"highp ");
600 assert(
false &&
"Invalid enum value");
606 case MaterialDataType::Unknown:
607 case MaterialDataType::Float:
608 case MaterialDataType::Float2:
609 case MaterialDataType::Float3:
610 case MaterialDataType::Float4:
613 case MaterialDataType::Int:
614 case MaterialDataType::Int2:
615 case MaterialDataType::Int3:
616 case MaterialDataType::Int4:
617 shaderSource.append(
"i");
620 case MaterialDataType::UInt:
621 case MaterialDataType::UInt2:
622 case MaterialDataType::UInt3:
623 case MaterialDataType::UInt4:
624 shaderSource.append(
"u");
627 LOG_ERROR(logger,
"Unexpected texture format: %s", DataTypeNames[
static_cast<size_t>(format) < std::size(DataTypeNames) ?
static_cast<size_t>(format) : 0]);
632 case TextureDimensions::Texture2D:
633 shaderSource.append(
"sampler2D ");
635 case TextureDimensions::TexureCube:
636 shaderSource.append(
"samplerCube ");
638 case TextureDimensions::Texture2DArray:
639 shaderSource.append(
"sampler2DArray ");
641 case TextureDimensions::Texture3D:
642 shaderSource.append(
"sampler3D ");
645 LOG_ERROR(logger,
"Unsupported texture type %d",
int(kind));
649 shaderSource.append(
";\n");
652 void addTextures(std::string& shaderSource,
653 const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen,
654 const std::vector<MaterialTextureDefinition>& definition)
656 for (
auto& texture : engineTextures) {
657 if (identifiersSeen.contains(texture.name)) {
658 shaderSource.append(
"#define COGS_");
659 shaderSource.append(Strings::get(texture.defineName).to_string_view());
660 shaderSource.append(
"_REFERENCED 1\n");
663 for (
auto& texture : definition) {
664 if (identifiersSeen.contains(Strings::add(texture.name))) {
665 addTextureDeclaration(shaderSource, texture.name, texture.dimensions, texture.format, texture.precision);
668 shaderSource.append(
"\n");
672bool addPermutationFragmentOutput(std::string& source,
const std::vector<EffectOutputMemberDefinition> outputDefinition,
const std::vector<std::pair<std::string, std::string>>& definitions,
bool depthOnly) {
673 bool outputDepth =
false;
674 bool hasColorAttachments = !outputDefinition.empty() && !depthOnly;
676 std::string targetString =
"COGS_CUSTOM_DEPTH_WRITE";
677 auto it = std::find_if(definitions.begin(), definitions.end(),
678 [&targetString](
const std::pair<std::string, std::string>& p) {
679 return p.first == targetString;
682 if (it != definitions.end()) {
683 outputDepth = it->second !=
"0";
686 if (!outputDepth && !hasColorAttachments) {
690 std::string outVariables;
692 source.append(
"struct FragmentOut {\n");
693 if (hasColorAttachments) {
694 for (
auto member : outputDefinition) {
695 outVariables.append(
"layout(location = " + std::to_string(member.target) +
") out " + std::string(attributeVaryingType(member.dataType)) +
"po_" + member.name +
";\n");
697 source.append(
" " + std::string(attributeVaryingType(member.dataType)) +
" " + member.name +
";\n");
701 source.append(
" float fragDepth;\n");
703 source.append(
"};\n");
704 source.append(outVariables);
708void addMainFunction(std::string& source,
const std::vector<EffectOutputMemberDefinition> outputDefinition,
const std::vector<std::pair<std::string, std::string>>& definitions,
bool depthOnly,
bool hasOutput) {
712 VertexIn In = importIn();
719 bool outputDepth =
false;
720 std::string targetString =
"COGS_CUSTOM_DEPTH_WRITE";
721 auto it = std::find_if(definitions.begin(), definitions.end(),
722 [&targetString](
const std::pair<std::string, std::string>& p) {
723 return p.first == targetString;
726 if (it != definitions.end()) {
727 outputDepth = it->second !=
"0";
730 source.append(
"void exportOut(FragmentOut Out) {\n");
732 for (
auto member : outputDefinition) {
733 source.append(
" po_");
734 source.append(member.name);
735 source.append(
" = Out.");
736 source.append(member.name);
737 source.append(
";\n");
741 source.append(
" gl_FragDepth = Out.fragDepth;\n");
743 source.append(
"}\n");
746 VertexIn In = importIn();
747 FragmentOut Out = permutationMain(In);
754 out.members.reserve(a.members.size() + b.members.size());
756 for (
auto member : b.members) {
758 for (
auto existingMember : a.members) {
759 if (member.name == existingMember.name) {
765 out.members.push_back(member);
770bool Cogs::Core::buildEffectES3(
Context* context,
771 std::vector<std::pair<std::string, std::string>>& definitions,
774 uint32_t multiViewCount)
776 if (!materialDefinition.effect.geometryShader.entryPoint.empty()) {
777 LOG_ERROR(logger,
"%s: Geometry shader not allowed in GLES3.", materialDefinition.name.c_str());
780 if (!materialDefinition.effect.hullShader.entryPoint.empty()) {
781 LOG_ERROR(logger,
"%s: Hull shader not allowed in GLES3.", materialDefinition.name.c_str());
784 if (!materialDefinition.effect.domainShader.entryPoint.empty()) {
785 LOG_ERROR(logger,
"%s: Domain shader not allowed in GLES3.", materialDefinition.name.c_str());
788 if (!materialDefinition.effect.computeShader.entryPoint.empty()) {
789 LOG_ERROR(logger,
"%s: Compute shader not allowed in GLES3.", materialDefinition.name.c_str());
793 changeSuffix(materialDefinition.effect.vertexShader.customSourcePath,
".hlsl",
".es30.glsl");
794 changeSuffix(materialDefinition.effect.pixelShader.customSourcePath,
".hlsl",
".es30.glsl");
795 std::string_view prefix = materialDefinition.name;
798 concatUniqueMembers(materialDefinition.effect.vertexShader.shaderInterface, permutation.getDefinition()->vertexInterface, vertexInterface);
800 concatUniqueMembers(materialDefinition.effect.pixelShader.shaderInterface, permutation.getDefinition()->surfaceInterface, surfaceInterface);
805 pp.
processed.reserve(::InitialBufferCapasity);
807 std::string vsheader;
808 vsheader.reserve(::InitialBufferCapasity);
809 addEffectDefinesAndStuff(vsheader, definitions, multiViewCount,
true);
810 vsheader.append(
"#define COGS_VERTEX_SHADER 1\n");
811 if (!pp.
process(context, vsheader))
return false;
816 vsbody.reserve(::InitialBufferCapasity);
817 addAttributes(vsbody, vertexInterface);
818 addInterfaceStruct(vsbody,
"VertexIn", vertexInterface);
819 addAttributeImportFunc(vsbody,
"VertexIn", vertexInterface);
820 addInOutVariables(vsbody,
"vsfs_",surfaceInterface,
false);
821 addInterfaceStruct(vsbody,
"VertexOut",surfaceInterface);
822 addInterfaceConstructor(vsbody,
"VertexOut",surfaceInterface);
823 addExportOutFunc(vsbody,
"VertexOut",surfaceInterface);
824 addTransferFunc(vsbody, materialDefinition.effect.vertexShader, materialDefinition.effect.pixelShader);
825 addInclude(vsbody,
Cogs::StringView(), materialDefinition.effect.vertexShader.customSourcePath);
827 vsbody.append(
"#define MATERIAL_VERTEX_FUNCTION ");
828 vsbody.append(materialDefinition.effect.vertexShader.entryPoint.empty() ?
"vertexFunction" : materialDefinition.effect.vertexShader.entryPoint);
832 vsbody.append(
"#define VERTEX_FUNCTION invokeMaterial\n");
833 std::string permutationVS = permutation.getDefinition()->vertexShader;
834 changeSuffix(permutationVS,
".hlsl",
".es30.glsl");
835 addInclude(vsbody,
nullptr, permutationVS);
837 if (!pp.
process(context, vsbody))
return false;
841 std::string vsuniforms;
842 vsuniforms.reserve(::InitialBufferCapasity);
850 addTextures(vsuniforms, pp.
identifiersSeen, materialDefinition.properties.textures);
853 if (!pp.
process(context, vsuniforms))
return false;
857 const std::string shaderName = Cogs::stringConcatenate({ prefix,
"VertexShader", permutation.getDefinition()->name,
".es30.glsl" });
858 const std::string all = Cogs::stringConcatenate({ vsheader, vsuniforms, vsbody });
862 FILE* f = fopen(shaderName.c_str(),
"wb");
863 fwrite(all.c_str(), all.length(), 1, f);
865 LOG_DEBUG(logger,
"Generated %s", shaderName.c_str());
869 std::string vspath =
"Shaders/" + shaderName;
875 pp.
processed.reserve(::InitialBufferCapasity);
877 std::string fsheader;
878 fsheader.reserve(::InitialBufferCapasity);
879 addEffectDefinesAndStuff(fsheader, definitions, multiViewCount,
false);
880 fsheader.append(
"#define COGS_FRAGMENT_SHADER 1\n");
881 if (!pp.
process(context, fsheader))
return false;
886 fsbody.reserve(::InitialBufferCapasity);
887 addInOutVariables(fsbody,
"vsfs_",surfaceInterface,
true);
888 addInterfaceStruct(fsbody,
"VertexIn",surfaceInterface);
889 addImportInFunc(fsbody,
"VertexIn",surfaceInterface);
890 addInclude(fsbody,
nullptr, materialDefinition.effect.pixelShader.customSourcePath);
892 fsbody.append(
"#define MATERIAL_SURFACE_FUNCTION ");
893 fsbody.append(materialDefinition.effect.pixelShader.entryPoint.empty() ?
"surfaceFunction" : materialDefinition.effect.pixelShader.entryPoint);
897 bool hasOutputStruct = addPermutationFragmentOutput(fsbody, permutation.getDefinition()->outputs.members, definitions, permutation.isDepthOnly());
899 fsbody.append(
"#define SURFACE_FUNCTION invokeMaterial\n");
900 std::string permutationPS = permutation.getDefinition()->pixelShader;
901 changeSuffix(permutationPS,
".hlsl",
".es30.glsl");
902 addInclude(fsbody,
nullptr, permutationPS);
904 if (!pp.
process(context, fsbody))
return false;
908 addMainFunction(fsbody, permutation.getDefinition()->outputs.members, definitions, permutation.isDepthOnly(), hasOutputStruct);
910 std::string fsuniforms;
911 fsuniforms.reserve(::InitialBufferCapasity);
919 addTextures(fsuniforms, pp.
identifiersSeen, materialDefinition.properties.textures);
920 addInclude(fsuniforms,
nullptr,
"Engine/Common.es30.glsl");
922 if (!pp.
process(context, fsuniforms))
return false;
926 const std::string shaderName = Cogs::stringConcatenate({ prefix,
"PixelShader", permutation.getDefinition()->name,
".es30.glsl" });
927 const std::string all = Cogs::stringConcatenate({ fsheader, fsuniforms, fsbody });
931 FILE* f = fopen(shaderName.c_str(),
"wb");
932 fwrite(all.c_str(), all.length(), 1, f);
934 LOG_DEBUG(logger,
"Generated %s", shaderName.c_str());
938 std::string fspath =
"Shaders/" + shaderName;
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class ResourceStore > resourceStore
ResourceStore service instance.
Log implementation class.
Provides a weakly referenced view over the contents of a string.
constexpr size_t size() const noexcept
Get the size of the string.
constexpr std::string_view to_string_view() const noexcept
Create a standard library string_view of the same view.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
TextureDimensions
Texture dimensions.
MaterialDataType
Defines available data types for material properties.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
bool process(Context *context, const StringView input)
Run a text block through the preprocessor.
std::unordered_set< StringRef > identifiersSeen
Set of identifiers encountered in active text.
std::string processed
Resulting processed text.