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(
"originHigh"),
52 Strings::add(
"originLow"),
53 Strings::add(
"blueNoiseOffset"),
54 Strings::add(
"viewportOrigin"),
55 Strings::add(
"viewportSize"),
56 Strings::add(
"viewportSizeRcp"),
57 Strings::add(
"shadowDepthClamp"),
58 Strings::add(
"animationTime"),
59 Strings::add(
"exposure"),
60 Strings::add(
"sceneFlags"),
61 Strings::add(
"clientFlags"),
62 Strings::add(
"environmentRadianceMips"),
63 Strings::add(
"environmentIrradianceMips"),
65 Strings::add(
"lightPositions"),
66 Strings::add(
"lightDirections"),
67 Strings::add(
"lightColorIntensity"),
68 Strings::add(
"lightParameters"),
69 Strings::add(
"numLights"),
70 Strings::add(
"eyePosition"),
71 Strings::add(
"fogColor"),
72 Strings::add(
"fogDistance"),
73 Strings::add(
"fogAmount"),
74 Strings::add(
"fogEnabled"),
75 Strings::add(
"ambientIntensity"),
76 Strings::add(
"ambientColor"),
77 Strings::add(
"environmentBrightness"),
78 Strings::add(
"skyMultiplier"),
79 Strings::add(
"seaFlags"),
80 Strings::add(
"flags"),
82 Strings::add(
"shadows"),
83 Strings::add(
"cascadeOffsets")
87 Strings::add(
"getPeriodicWorldPos"),
88 Strings::add(
"getPeriodicWorldPosAndCell")
92 Strings::add(
"getClipFromViewMatrix"),
93 Strings::add(
"getClipFromWorldMatrix"),
94 Strings::add(
"getViewFromWorldMatrix"),
95 Strings::add(
"getViewFromClipMatrix"),
96 Strings::add(
"getWorldFromViewMatrix"),
97 Strings::add(
"getViewFromViewportMatrix")
101 Strings::add(
"worldMatrix"),
102 Strings::add(
"objectId")
106 Strings::add(
"boneTransforms")
109 struct EngineBuffer {
113 } engineBuffers[] = {
114 { sceneBufferMembers,
sizeof(sceneBufferMembers) /
sizeof(sceneBufferMembers[0]), Strings::add(
"SCENEBUFFER") },
115 { sceneGetters,
sizeof(sceneGetters) /
sizeof(sceneGetters[0]), Strings::add(
"SCENEGETTERS") },
116 { viewGetters,
sizeof(viewGetters) /
sizeof(viewGetters[0]), Strings::add(
"VIEWGETTERS") },
117 { objectBufferMembers,
sizeof(objectBufferMembers) /
sizeof(objectBufferMembers[0]), Strings::add(
"OBJECTBUFFER") },
118 { animationBufferMembers,
sizeof(animationBufferMembers) /
sizeof(animationBufferMembers[0]), Strings::add(
"ANIMATIONBUFFER") }
125 content.append(
"#include \"");
127 content.append(path.to_string_view());
128 content.append(
"\"\n");
131 void changeSuffix(std::string& dst,
const std::string_view& from,
const std::string_view& to)
133 auto pos = dst.find(from);
134 if (pos == std::string::npos)
return;
135 dst.replace(pos, to.length(), to);
138 void addEffectDefinesAndStuff(std::string& output,
139 const std::vector<std::pair<std::string, std::string>>& definitions,
140 uint32_t multiViewCount,
bool isVertexShader)
142 output.append(
"#version 300 es\n");
143 if (multiViewCount) {
144 std::string multiViewCountString = std::to_string(multiViewCount);
145 if (isVertexShader) {
146 output.append(
"#extension GL_OVR_multiview : require\nlayout(num_views=");
147 output.append(multiViewCountString);
148 output.append(
") in;\n");
150 output.append(
"#define COGS_MULTIVIEW ");
151 output.append(multiViewCountString);
154 output.append(
"precision highp float;\n"
155 "precision highp int;\n"
156 "precision highp sampler2DArrayShadow;\n"
157 "precision highp samplerCubeShadow;\n"
158 "precision mediump sampler2DArray;\n"
159 "precision highp isampler2D;\n"
160 "precision highp usampler2D;\n"
161 "precision highp usampler2DArray;\n"
162 "precision highp isampler2DArray;\n"
163 "layout (std140) uniform;\n");
164 for (
const std::pair<std::string,std::string>& define : definitions) {
165 output.append(
"#define ");
166 output.append(define.first);
168 output.append(define.second);
173 [[nodiscard]] std::string_view attributeVaryingType(
const MaterialDataType type)
176 case MaterialDataType::Float:
return "float ";
break;
177 case MaterialDataType::Float2:
return "vec2 ";
break;
178 case MaterialDataType::Float3:
return "vec3 ";
break;
179 case MaterialDataType::Float4:
return "vec4 ";
break;
180 case MaterialDataType::Float4x4:
return "mat4 ";
break;
181 case MaterialDataType::Int:
return "int ";
break;
182 case MaterialDataType::Int2:
return "ivec4 ";
break;
183 case MaterialDataType::Int3:
return "ivec3 ";
break;
184 case MaterialDataType::Int4:
return "ivec4 ";
break;
185 case MaterialDataType::UInt:
return "uint ";
break;
186 case MaterialDataType::UInt2:
return "uvec4 ";
break;
187 case MaterialDataType::UInt3:
return "uvec3 ";
break;
188 case MaterialDataType::UInt4:
return "uvec4 ";
break;
189 case MaterialDataType::SV_IsFrontFace:
return "bool ";
break;
190 case MaterialDataType::VFACE:
return "float ";
break;
191 case MaterialDataType::Position:
return "vec4 ";
break;
193 LOG_ERROR(logger,
"Unsupported attribute type %d",
int(type));
199 const char* semanticNames[]
209 static_assert(
sizeof(semanticNames) ==
sizeof(semanticNames[0]) * (size_t(ShaderInterfaceMemberDefinition::SemanticName::FirstSystemValueSemantic) - 1));
215 if ((attribute.semantic.name != ShaderInterfaceMemberDefinition::SemanticName::None)
216 && (
size_t(attribute.semantic.name) <
size_t(ShaderInterfaceMemberDefinition::SemanticName::FirstSystemValueSemantic)))
218 shaderSource.append(
"in ");
219 shaderSource.append(attributeVaryingType(attribute.type));
220 shaderSource.append(semanticNames[
size_t(attribute.semantic.name) - 1]);
221 shaderSource.append(std::to_string(attribute.semantic.slot));
222 shaderSource.append(
";\n");
225 switch (attribute.semantic.name) {
226 case ShaderInterfaceMemberDefinition::SemanticName::SV_VertexID: [[fallthrough]];
227 case ShaderInterfaceMemberDefinition::SemanticName::SV_InstanceID:
230 LOG_WARNING(logger,
"Unexpected semantic name '%.*s'",
231 StringViewFormat(ShaderInterfaceMemberDefinition::semanticNameString(attribute.semantic.name)));
235 shaderSource.append(
"\n");
240 shaderSource.append(
"struct ");
241 shaderSource.append(name);
242 shaderSource.append(
" {\n");
243 for (
const auto& attribute : iface.members) {
244 shaderSource.append(
" ");
245 shaderSource.append(attributeVaryingType(attribute.type));
246 shaderSource.append(attribute.name);
247 shaderSource.append(
";\n");
249 shaderSource.append(
"};\n\n");
252 void addAttributeImportFunc(std::string& shaderSource,
const std::string_view& name,
const ShaderInterfaceDefinition& iface)
254 shaderSource.append(name);
255 shaderSource.append(
" importAttributes() {\n");
256 shaderSource.append(
" ");
257 shaderSource.append(name);
258 shaderSource.append(
" t;\n");
259 for (
const auto& attribute : iface.members) {
262 if ((attribute.semantic.name != ShaderInterfaceMemberDefinition::SemanticName::None)
263 && (
size_t(attribute.semantic.name) <
size_t(ShaderInterfaceMemberDefinition::SemanticName::FirstSystemValueSemantic)))
265 shaderSource.append(
" t.");
266 shaderSource.append(attribute.name);
267 shaderSource.append(
" = ");
268 shaderSource.append(semanticNames[
size_t(attribute.semantic.name) - 1]);
269 shaderSource.append(std::to_string(attribute.semantic.slot));
270 shaderSource.append(
";\n");
273 switch (attribute.semantic.name) {
274 case ShaderInterfaceMemberDefinition::SemanticName::SV_VertexID:
275 shaderSource.append(
" t.");
276 shaderSource.append(attribute.name);
277 shaderSource.append(
" = ");
278 shaderSource.append(attributeVaryingType(attribute.type));
279 shaderSource.append(
"(gl_VertexID);\n");
281 case ShaderInterfaceMemberDefinition::SemanticName::SV_InstanceID:
282 shaderSource.append(
" t.");
283 shaderSource.append(attribute.name);
284 shaderSource.append(
" = ");
285 shaderSource.append(attributeVaryingType(attribute.type));
286 shaderSource.append(
"(gl_InstanceID);\n");
293 shaderSource.append(
" return t;\n}\n\n");
296 void addInOutVariables(std::string& shaderSource,
const std::string_view& prefix,
const ShaderInterfaceDefinition& iface,
bool in)
298 if (iface.members.empty())
return;
299 for (
const auto& out : iface.members) {
301 case MaterialDataType::SV_IsFrontFace:
302 case MaterialDataType::VFACE:
306 if (out.modifiers & ShaderInterfaceMemberDefinition::CentroidModifier) {
307 shaderSource.append(
"centroid ");
309 if (out.modifiers & ShaderInterfaceMemberDefinition::NointerpolationModifier) {
310 shaderSource.append(
"flat ");
312 shaderSource.append(in ?
"in " :
"out ");
313 shaderSource.append(attributeVaryingType(out.type));
314 shaderSource.append(prefix);
315 shaderSource.append(out.name);
316 shaderSource.append(
";\n");
320 shaderSource.append(
"\n");
323 void addInterfaceConstructor(std::string& shaderSource,
const std::string_view& name,
const ShaderInterfaceDefinition& iface)
325 shaderSource.append(name);
326 shaderSource.append(
" create");
327 shaderSource.append(name);
328 shaderSource.append(
"() {\n");
329 shaderSource.append(
" ");
330 shaderSource.append(name);
331 shaderSource.append(
" t;\n");
332 for (
const auto& attribute : iface.members) {
333 const char* initializer =
nullptr;
334 switch (attribute.type) {
335 case MaterialDataType::Float: initializer =
"0.0;\n";
break;
336 case MaterialDataType::Float2: initializer =
"vec2(0);\n";
break;
337 case MaterialDataType::Float3: initializer =
"vec3(0);\n";
break;
338 case MaterialDataType::Float4: initializer =
"vec4(0);\n";
break;
339 case MaterialDataType::Float4x4: initializer =
"mat4(0);\n";
break;
344 shaderSource.append(
" t.");
345 shaderSource.append(attribute.name);
346 shaderSource.append(
" = ");
347 shaderSource.append(initializer);
350 shaderSource.append(
" return t;\n}\n\n");
355 shaderSource.append(
"void exportOut(");
356 shaderSource.append(name);
357 shaderSource.append(
" vertexOut) {\n");
358 for (
const auto& attribute : iface.members) {
359 switch (attribute.type) {
360 case MaterialDataType::SV_IsFrontFace:
361 case MaterialDataType::VFACE:
365 shaderSource.append(
" vsfs_");
366 shaderSource.append(attribute.name);
367 shaderSource.append(
" = vertexOut.");
368 shaderSource.append(attribute.name);
369 shaderSource.append(
";\n");
373 shaderSource.append(
"}\n");
378 shaderSource.append(name);
379 shaderSource.append(
" importIn() {\n ");
380 shaderSource.append(name);
381 shaderSource.append(
" t;\n");
382 for (
const auto& attribute : iface.members) {
383 switch (attribute.type) {
384 case MaterialDataType::SV_IsFrontFace:
385 shaderSource.append(
" t.");
386 shaderSource.append(attribute.name);
387 shaderSource.append(
" = gl_FrontFacing;\n");
389 case MaterialDataType::VFACE:
390 shaderSource.append(
" t.");
391 shaderSource.append(attribute.name);
392 shaderSource.append(
" = gl_FrontFacing ? 1.0 : -1.0;\n");
394 case MaterialDataType::Position:
395 shaderSource.append(
" t.");
396 shaderSource.append(attribute.name);
397 shaderSource.append(
" = gl_FragCoord;\n");
400 shaderSource.append(
" t.");
401 shaderSource.append(attribute.name);
402 shaderSource.append(
" = vsfs_");
403 shaderSource.append(attribute.name);
404 shaderSource.append(
";\n");
408 shaderSource.append(
" return t;\n}\n");
413 shaderSource.append(
"void transferAttributes(in VertexIn vertexIn, inout VertexOut vertexOut) {\n");
415 if (member.semantic.name == ShaderInterfaceMemberDefinition::SemanticName::SV_VertexID)
continue;
417 if (dMember.name == member.name) {
418 shaderSource.append(
" vertexOut.");
419 shaderSource.append(member.name);
420 shaderSource.append(
" = ");
421 if (dMember.type == MaterialDataType::Float3 && member.type == MaterialDataType::Float2 && member.semantic.name == ShaderInterfaceMemberDefinition::SemanticName::Normal) {
422 shaderSource.append(
"octDecode(vertexIn.");
423 shaderSource.append(member.name);
424 shaderSource.append(
"); \n");
427 if (dMember.type == MaterialDataType::Float4 && member.type == MaterialDataType::Float3) {
428 shaderSource.append(
"vec4(vertexIn.");
429 shaderSource.append(member.name);
430 shaderSource.append(
", 1.0);\n");
433 if (dMember.type == MaterialDataType::Float4 && member.type == MaterialDataType::Float2) {
434 shaderSource.append(
"vec4(vertexIn.");
435 shaderSource.append(member.name);
436 shaderSource.append(
", 0.0, 1.0);\n");
440 if (dMember.type != member.type) {
441 switch (dMember.type) {
442 case MaterialDataType::Float: shaderSource.append(
"float("); close =
true;
break;
443 case MaterialDataType::Float2: shaderSource.append(
"vec2("); close =
true;
break;
444 case MaterialDataType::Float3: shaderSource.append(
"vec3("); close =
true;
break;
445 case MaterialDataType::Float4: shaderSource.append(
"vec4("); close =
true;
break;
446 case MaterialDataType::Float4x4: shaderSource.append(
"mat4("); close =
true;
break;
447 case MaterialDataType::Int: shaderSource.append(
"int("); close =
true;
break;
448 case MaterialDataType::Int2: shaderSource.append(
"ivec2("); close =
true;
break;
449 case MaterialDataType::Int3: shaderSource.append(
"ivec3("); close =
true;
break;
450 case MaterialDataType::Int4: shaderSource.append(
"ivec4("); close =
true;
break;
451 case MaterialDataType::UInt: shaderSource.append(
"uint("); close =
true;
break;
452 case MaterialDataType::UInt2: shaderSource.append(
"uvec2("); close =
true;
break;
453 case MaterialDataType::UInt3: shaderSource.append(
"uvec3("); close =
true;
break;
454 case MaterialDataType::UInt4: shaderSource.append(
"uvec4("); close =
true;
break;
459 shaderSource.append(
"vertexIn.");
460 shaderSource.append(member.name);
461 if (close) shaderSource.append(1,
')');
462 shaderSource.append(
";\n");
467 shaderSource.append(
"}\n");
471 void addEngineUniformBuffer(std::string& shaderSource,
const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen)
473 for (
const EngineBuffer& engineBuffer : engineBuffers) {
476 bool referenced =
false;
477 for (
size_t i = 0; i < engineBuffer.count; i++) {
478 if (identifiersSeen.contains(engineBuffer.members[i])) {
487 shaderSource.append(
"#define COGS_");
488 shaderSource.append(Strings::get(engineBuffer.name).to_string_view());
489 shaderSource.append(
"_REFERENCED 1\n");
494 void addUniformBuffer(std::string& shaderSource,
495 const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen,
498 if (definition.values.empty())
return;
501 bool isInUse =
false;
503 if (identifiersSeen.contains(Strings::add(member.name))) {
508 if (!isInUse)
return;
511 shaderSource.append(
"uniform ");
512 shaderSource.append(definition.name);
513 shaderSource.append(
" {\n");
515 shaderSource.append(2,
' ');
516 switch (member.type) {
517 case MaterialDataType::Float: shaderSource.append(
"float");
break;
518 case MaterialDataType::Float2: shaderSource.append(
"vec2");
break;
519 case MaterialDataType::Float3: shaderSource.append(
"vec3");
break;
520 case MaterialDataType::Float4: shaderSource.append(
"vec4");
break;
521 case MaterialDataType::Float4x4: shaderSource.append(
"mat4");
break;
522 case MaterialDataType::Float4Array: shaderSource.append(
"vec4");
break;
523 case MaterialDataType::Float4x4Array: shaderSource.append(
"mat4");
break;
524 case MaterialDataType::Int: shaderSource.append(
"int");
break;
525 case MaterialDataType::Int2: shaderSource.append(
"ivec2");
break;
526 case MaterialDataType::Int3: shaderSource.append(
"ivec3");
break;
527 case MaterialDataType::Int4: shaderSource.append(
"ivec4");
break;
528 case MaterialDataType::UInt: shaderSource.append(
"uint");
break;
529 case MaterialDataType::UInt2: shaderSource.append(
"uvec2");
break;
530 case MaterialDataType::UInt3: shaderSource.append(
"uvec3");
break;
531 case MaterialDataType::UInt4: shaderSource.append(
"uvec4");
break;
532 case MaterialDataType::Bool: shaderSource.append(
"bool");
break;
534 shaderSource.append(
"<invalid type>");
537 shaderSource.append(1,
' ');
538 shaderSource.append(member.name);
539 if (member.type == MaterialDataType::Float4Array || member.type == MaterialDataType::Float4x4Array) {
540 assert(member.dimension !=
static_cast<size_t>(-1));
541 shaderSource.append(
"[");
542 shaderSource.append(std::to_string(member.dimension));
543 shaderSource.append(
"]");
545 shaderSource.append(
";\n");
547 shaderSource.append(
"};\n");
551 void addEngineUniforms(std::string& shaderSource,
const std::unordered_set<StringRef>& identifiersSeen)
553 for (
auto& item : engineUniforms) {
554 bool active = identifiersSeen.count(item.name);
555 for (
auto dependee : item.dependees) {
556 active = active || identifiersSeen.count(dependee);
559 shaderSource.append(
"uniform ");
561 case MaterialDataType::Float4:
562 shaderSource.append(
"vec4 ");
564 case MaterialDataType::Float4x4:
565 shaderSource.append(
"mat4 ");
568 assert(
false &&
"Unhandled material data type");
570 auto name = Strings::get(item.name);
571 shaderSource.append(name.to_string_view());
572 shaderSource.append(
";\n");
575 if (identifiersSeen.count(objectId)) shaderSource.append(
"float objectId() { return objectData.x; }\n");
576 if (identifiersSeen.count(animationTime)) shaderSource.append(
"float animationTime() { return objectData.y; }\n");
577 if (identifiersSeen.count(environmentRadianceMips)) shaderSource.append(
"float environmentRadianceMips() { return environmentInfo.x; }\n");
578 if (identifiersSeen.count(environmentIrradianceMips)) shaderSource.append(
"float environmentIrradianceMips() { return environmentInfo.y; }\n");
579 if (identifiersSeen.count(exposure)) shaderSource.append(
"float exposure() { return environmentInfo.z; }\n");
580 if (identifiersSeen.count(environmentBrightness)) shaderSource.append(
"float environmentBrightness() { return environmentInfo.w; }\n");
587 shaderSource.append(
"uniform ");
590 case MaterialTypePrecision::Default:
592 case MaterialTypePrecision::Low:
593 shaderSource.append(
"lowp ");
595 case MaterialTypePrecision::Medium:
596 shaderSource.append(
"mediump ");
598 case MaterialTypePrecision::High:
599 shaderSource.append(
"highp ");
602 assert(
false &&
"Invalid enum value");
608 case MaterialDataType::Unknown:
609 case MaterialDataType::Float:
610 case MaterialDataType::Float2:
611 case MaterialDataType::Float3:
612 case MaterialDataType::Float4:
615 case MaterialDataType::Int:
616 case MaterialDataType::Int2:
617 case MaterialDataType::Int3:
618 case MaterialDataType::Int4:
619 shaderSource.append(
"i");
622 case MaterialDataType::UInt:
623 case MaterialDataType::UInt2:
624 case MaterialDataType::UInt3:
625 case MaterialDataType::UInt4:
626 shaderSource.append(
"u");
629 LOG_ERROR(logger,
"Unexpected texture format: %s", DataTypeNames[
static_cast<size_t>(format) < std::size(DataTypeNames) ?
static_cast<size_t>(format) : 0]);
634 case TextureDimensions::Texture2D:
635 shaderSource.append(
"sampler2D ");
637 case TextureDimensions::TexureCube:
638 shaderSource.append(
"samplerCube ");
640 case TextureDimensions::Texture2DArray:
641 shaderSource.append(
"sampler2DArray ");
643 case TextureDimensions::Texture3D:
644 shaderSource.append(
"sampler3D ");
647 LOG_ERROR(logger,
"Unsupported texture type %d",
int(kind));
651 shaderSource.append(
";\n");
654 void addTextures(std::string& shaderSource,
655 const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen,
656 const std::vector<MaterialTextureDefinition>& definition)
658 for (
auto& texture : engineTextures) {
659 if (identifiersSeen.contains(texture.name)) {
660 shaderSource.append(
"#define COGS_");
661 shaderSource.append(Strings::get(texture.defineName).to_string_view());
662 shaderSource.append(
"_REFERENCED 1\n");
665 for (
auto& texture : definition) {
666 if (identifiersSeen.contains(Strings::add(texture.name))) {
667 addTextureDeclaration(shaderSource, texture.name, texture.dimensions, texture.format, texture.precision);
670 shaderSource.append(
"\n");
674bool addPermutationFragmentOutput(std::string& source,
const std::vector<EffectOutputMemberDefinition> outputDefinition,
const std::vector<std::pair<std::string, std::string>>& definitions,
bool depthOnly) {
675 bool outputDepth =
false;
676 bool hasColorAttachments = !outputDefinition.empty() && !depthOnly;
678 std::string targetString =
"COGS_CUSTOM_DEPTH_WRITE";
679 auto it = std::find_if(definitions.begin(), definitions.end(),
680 [&targetString](
const std::pair<std::string, std::string>& p) {
681 return p.first == targetString;
684 if (it != definitions.end()) {
685 outputDepth = it->second !=
"0";
688 if (!outputDepth && !hasColorAttachments) {
692 std::string outVariables;
694 source.append(
"struct FragmentOut {\n");
695 if (hasColorAttachments) {
696 for (
auto member : outputDefinition) {
697 outVariables.append(
"layout(location = " + std::to_string(member.target) +
") out " + std::string(attributeVaryingType(member.dataType)) +
"po_" + member.name +
";\n");
699 source.append(
" " + std::string(attributeVaryingType(member.dataType)) +
" " + member.name +
";\n");
703 source.append(
" float fragDepth;\n");
705 source.append(
"};\n");
706 source.append(outVariables);
710void addMainFunction(std::string& source,
const std::vector<EffectOutputMemberDefinition> outputDefinition,
const std::vector<std::pair<std::string, std::string>>& definitions,
bool depthOnly,
bool hasOutput) {
714 VertexIn In = importIn();
721 bool outputDepth =
false;
722 std::string targetString =
"COGS_CUSTOM_DEPTH_WRITE";
723 auto it = std::find_if(definitions.begin(), definitions.end(),
724 [&targetString](
const std::pair<std::string, std::string>& p) {
725 return p.first == targetString;
728 if (it != definitions.end()) {
729 outputDepth = it->second !=
"0";
732 source.append(
"void exportOut(FragmentOut Out) {\n");
734 for (
auto member : outputDefinition) {
735 source.append(
" po_");
736 source.append(member.name);
737 source.append(
" = Out.");
738 source.append(member.name);
739 source.append(
";\n");
743 source.append(
" gl_FragDepth = Out.fragDepth;\n");
745 source.append(
"}\n");
748 VertexIn In = importIn();
749 FragmentOut Out = permutationMain(In);
756 out.members.reserve(a.members.size() + b.members.size());
758 for (
auto member : b.members) {
760 for (
auto existingMember : a.members) {
761 if (member.name == existingMember.name) {
767 out.members.push_back(member);
772bool Cogs::Core::buildEffectES3(
Context* context,
773 std::vector<std::pair<std::string, std::string>>& definitions,
776 uint32_t multiViewCount)
778 if (!materialDefinition.effect.geometryShader.entryPoint.empty()) {
779 LOG_ERROR(logger,
"%s: Geometry shader not allowed in GLES3.", materialDefinition.name.c_str());
782 if (!materialDefinition.effect.hullShader.entryPoint.empty()) {
783 LOG_ERROR(logger,
"%s: Hull shader not allowed in GLES3.", materialDefinition.name.c_str());
786 if (!materialDefinition.effect.domainShader.entryPoint.empty()) {
787 LOG_ERROR(logger,
"%s: Domain shader not allowed in GLES3.", materialDefinition.name.c_str());
790 if (!materialDefinition.effect.computeShader.entryPoint.empty()) {
791 LOG_ERROR(logger,
"%s: Compute shader not allowed in GLES3.", materialDefinition.name.c_str());
795 changeSuffix(materialDefinition.effect.vertexShader.customSourcePath,
".hlsl",
".es30.glsl");
796 changeSuffix(materialDefinition.effect.pixelShader.customSourcePath,
".hlsl",
".es30.glsl");
797 std::string_view prefix = materialDefinition.name;
800 concatUniqueMembers(materialDefinition.effect.vertexShader.shaderInterface, permutation.getDefinition()->vertexInterface, vertexInterface);
802 concatUniqueMembers(materialDefinition.effect.pixelShader.shaderInterface, permutation.getDefinition()->surfaceInterface, surfaceInterface);
807 pp.
processed.reserve(::InitialBufferCapasity);
809 std::string vsheader;
810 vsheader.reserve(::InitialBufferCapasity);
811 addEffectDefinesAndStuff(vsheader, definitions, multiViewCount,
true);
812 vsheader.append(
"#define COGS_VERTEX_SHADER 1\n");
813 if (!pp.
process(context, vsheader))
return false;
818 vsbody.reserve(::InitialBufferCapasity);
819 addAttributes(vsbody, vertexInterface);
820 addInterfaceStruct(vsbody,
"VertexIn", vertexInterface);
821 addAttributeImportFunc(vsbody,
"VertexIn", vertexInterface);
822 addInOutVariables(vsbody,
"vsfs_",surfaceInterface,
false);
823 addInterfaceStruct(vsbody,
"VertexOut",surfaceInterface);
824 addInterfaceConstructor(vsbody,
"VertexOut",surfaceInterface);
825 addExportOutFunc(vsbody,
"VertexOut",surfaceInterface);
826 addTransferFunc(vsbody, materialDefinition.effect.vertexShader, materialDefinition.effect.pixelShader);
827 addInclude(vsbody,
Cogs::StringView(), materialDefinition.effect.vertexShader.customSourcePath);
829 vsbody.append(
"#define MATERIAL_VERTEX_FUNCTION ");
830 vsbody.append(materialDefinition.effect.vertexShader.entryPoint.empty() ?
"vertexFunction" : materialDefinition.effect.vertexShader.entryPoint);
834 vsbody.append(
"#define VERTEX_FUNCTION invokeMaterial\n");
835 std::string permutationVS = permutation.getDefinition()->vertexShader;
836 changeSuffix(permutationVS,
".hlsl",
".es30.glsl");
837 addInclude(vsbody,
nullptr, permutationVS);
839 if (!pp.
process(context, vsbody))
return false;
843 std::string vsuniforms;
844 vsuniforms.reserve(::InitialBufferCapasity);
852 addTextures(vsuniforms, pp.
identifiersSeen, materialDefinition.properties.textures);
855 if (!pp.
process(context, vsuniforms))
return false;
859 const std::string shaderName = Cogs::stringConcatenate({ prefix,
"VertexShader", permutation.getDefinition()->name,
".es30.glsl" });
860 const std::string all = Cogs::stringConcatenate({ vsheader, vsuniforms, vsbody });
863#ifndef __EMSCRIPTEN__
864 FILE* f = fopen(shaderName.c_str(),
"wb");
865 fwrite(all.c_str(), all.length(), 1, f);
867 LOG_DEBUG(logger,
"Generated %s", shaderName.c_str());
871 std::string vspath =
"Shaders/" + shaderName;
877 pp.
processed.reserve(::InitialBufferCapasity);
879 std::string fsheader;
880 fsheader.reserve(::InitialBufferCapasity);
881 addEffectDefinesAndStuff(fsheader, definitions, multiViewCount,
false);
882 fsheader.append(
"#define COGS_FRAGMENT_SHADER 1\n");
883 if (!pp.
process(context, fsheader))
return false;
888 fsbody.reserve(::InitialBufferCapasity);
889 addInOutVariables(fsbody,
"vsfs_",surfaceInterface,
true);
890 addInterfaceStruct(fsbody,
"VertexIn",surfaceInterface);
891 addImportInFunc(fsbody,
"VertexIn",surfaceInterface);
892 addInclude(fsbody,
nullptr, materialDefinition.effect.pixelShader.customSourcePath);
894 fsbody.append(
"#define MATERIAL_SURFACE_FUNCTION ");
895 fsbody.append(materialDefinition.effect.pixelShader.entryPoint.empty() ?
"surfaceFunction" : materialDefinition.effect.pixelShader.entryPoint);
899 bool hasOutputStruct = addPermutationFragmentOutput(fsbody, permutation.getDefinition()->outputs.members, definitions, permutation.isDepthOnly());
901 fsbody.append(
"#define SURFACE_FUNCTION invokeMaterial\n");
902 std::string permutationPS = permutation.getDefinition()->pixelShader;
903 changeSuffix(permutationPS,
".hlsl",
".es30.glsl");
904 addInclude(fsbody,
nullptr, permutationPS);
906 if (!pp.
process(context, fsbody))
return false;
910 addMainFunction(fsbody, permutation.getDefinition()->outputs.members, definitions, permutation.isDepthOnly(), hasOutputStruct);
912 std::string fsuniforms;
913 fsuniforms.reserve(::InitialBufferCapasity);
921 addTextures(fsuniforms, pp.
identifiersSeen, materialDefinition.properties.textures);
922 addInclude(fsuniforms,
nullptr,
"Engine/Common.es30.glsl");
924 if (!pp.
process(context, fsuniforms))
return false;
928 const std::string shaderName = Cogs::stringConcatenate({ prefix,
"PixelShader", permutation.getDefinition()->name,
".es30.glsl" });
929 const std::string all = Cogs::stringConcatenate({ fsheader, fsuniforms, fsbody });
932#ifndef __EMSCRIPTEN__
933 FILE* f = fopen(shaderName.c_str(),
"wb");
934 fwrite(all.c_str(), all.length(), 1, f);
936 LOG_DEBUG(logger,
"Generated %s", shaderName.c_str());
940 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.