|
@@ -1,4 +1,8 @@
|
|
|
import { Tools } from '../../Misc/tools';
|
|
|
+import { ShaderCodeNode } from './shaderCodeNode';
|
|
|
+import { ShaderCodeCursor } from './shaderCodeCursor';
|
|
|
+import { ShaderCodeArithmeticTestNode } from './shaderCodeArithmeticTestNode';
|
|
|
+import { ShaderCodeDefineTestNode } from './shaderCodeDefineTestNode';
|
|
|
|
|
|
/** @hidden */
|
|
|
interface ProcessingOptions {
|
|
@@ -13,31 +17,6 @@ interface ProcessingOptions {
|
|
|
}
|
|
|
|
|
|
/** @hidden */
|
|
|
-class ShaderCodeNode {
|
|
|
- line: string;
|
|
|
- next: ShaderCodeNode;
|
|
|
- parent?: ShaderCodeNode;
|
|
|
- defineCondition?: string;
|
|
|
- child?: ShaderCodeNode;
|
|
|
-}
|
|
|
-
|
|
|
-/** @hidden */
|
|
|
-class ShaderCodeCursor {
|
|
|
- lines: string[];
|
|
|
- lineIndex: number;
|
|
|
- currentNode?: ShaderCodeNode;
|
|
|
- parentNode?: ShaderCodeNode;
|
|
|
-
|
|
|
- get currentLine(): string {
|
|
|
- return this.lines[this.lineIndex].trim();
|
|
|
- }
|
|
|
-
|
|
|
- get eof(): boolean {
|
|
|
- return this.lineIndex >= this.lines.length;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/** @hidden */
|
|
|
export class ShaderProcessor {
|
|
|
public static Process(sourceCode: string, options: ProcessingOptions, callback: (migratedCode: string) => void) {
|
|
|
this._ProcessIncludes(sourceCode, options, (codeWithIncludes) => {
|
|
@@ -64,7 +43,7 @@ export class ShaderProcessor {
|
|
|
return source;
|
|
|
}
|
|
|
|
|
|
- private static _EvaluatePreProcessors(sourceCode: string, preprocessors: string[]): string {
|
|
|
+ private static _EvaluatePreProcessors(sourceCode: string, preprocessors: {[key: string]: string}): string {
|
|
|
const rootNode = new ShaderCodeNode();
|
|
|
let cursor = new ShaderCodeCursor();
|
|
|
|
|
@@ -76,10 +55,10 @@ export class ShaderProcessor {
|
|
|
while (!cursor.eof) {
|
|
|
let line = cursor.currentLine;
|
|
|
if (line[0] === "#") {
|
|
|
- let first5 = line.substring(0, 5).toLowerCase();
|
|
|
- if (first5 === "#ifdef") {
|
|
|
- let newNode = new ShaderCodeNode();
|
|
|
- newNode.defineCondition = line.substring(5);
|
|
|
+ let first6 = line.substring(0, 6).toLowerCase();
|
|
|
+ if (first6 === "#ifdef") {
|
|
|
+ let newNode = new ShaderCodeDefineTestNode();
|
|
|
+ newNode.define = line.substring(6).trim();
|
|
|
newNode.parent = cursor.parentNode;
|
|
|
newNode.child = new ShaderCodeNode();
|
|
|
|
|
@@ -88,9 +67,24 @@ export class ShaderProcessor {
|
|
|
cursor.currentNode.next = newNode;
|
|
|
}
|
|
|
cursor.currentNode = newNode.child;
|
|
|
- } else if (first5 === "#endif") {
|
|
|
- cursor.parentNode = cursor.parentNode!.parent;
|
|
|
+ } else if (first6 === "#endif") {
|
|
|
cursor.currentNode = cursor.parentNode;
|
|
|
+ cursor.parentNode = cursor.parentNode!.parent;
|
|
|
+ }else if (line.substring(0, 3).toLowerCase() === "#if") {
|
|
|
+ let newNode = new ShaderCodeArithmeticTestNode();
|
|
|
+ let regex = /(.+)(.)(.+)/;
|
|
|
+ let matches = regex.exec(line.substring(3).trim())!;
|
|
|
+ newNode.define = matches[1];
|
|
|
+ newNode.operand = matches[2];
|
|
|
+ newNode.testValue = matches[3];
|
|
|
+ newNode.parent = cursor.parentNode;
|
|
|
+ newNode.child = new ShaderCodeNode();
|
|
|
+
|
|
|
+ cursor.parentNode = newNode;
|
|
|
+ if (cursor.currentNode) {
|
|
|
+ cursor.currentNode.next = newNode;
|
|
|
+ }
|
|
|
+ cursor.currentNode = newNode.child;
|
|
|
}
|
|
|
} else {
|
|
|
let newNode = new ShaderCodeNode();
|
|
@@ -112,16 +106,12 @@ export class ShaderProcessor {
|
|
|
let processedCode = "";
|
|
|
|
|
|
while (currentNode) {
|
|
|
- if (currentNode.defineCondition) {
|
|
|
- if (preprocessors.indexOf(currentNode.defineCondition)) {
|
|
|
- currentNode = currentNode.child!;
|
|
|
- }
|
|
|
- } else {
|
|
|
+ if (currentNode.line) {
|
|
|
processedCode += currentNode.line + "\r\n";
|
|
|
- currentNode = currentNode.next;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
+ currentNode = currentNode.getNextNode(preprocessors);
|
|
|
+ }
|
|
|
|
|
|
return processedCode;
|
|
|
}
|
|
@@ -139,7 +129,15 @@ export class ShaderProcessor {
|
|
|
return preparedSourceCode.replace("#version 300 es", "");
|
|
|
}
|
|
|
|
|
|
- let preprocessors = options.defines.split("\n");
|
|
|
+ let defines = options.defines.split("\n");
|
|
|
+
|
|
|
+ let preprocessors: {[key: string]: string} = {};
|
|
|
+
|
|
|
+ for (var define of defines) {
|
|
|
+ let keyValue = define.replace("#define", "").trim();
|
|
|
+ let split = keyValue.split(" ");
|
|
|
+ preprocessors[split[0]] = split.length > 1 ? split[1] : "";
|
|
|
+ }
|
|
|
|
|
|
preparedSourceCode = this._EvaluatePreProcessors(preparedSourceCode, preprocessors);
|
|
|
|
|
@@ -171,7 +169,7 @@ export class ShaderProcessor {
|
|
|
}
|
|
|
|
|
|
// Add multiview setup to top of file when defined
|
|
|
- var hasMultiviewExtension = preprocessors.indexOf("#define MULTIVIEW") !== -1;
|
|
|
+ var hasMultiviewExtension = defines.indexOf("#define MULTIVIEW") !== -1;
|
|
|
if (hasMultiviewExtension && !isFragment) {
|
|
|
result = "#extension GL_OVR_multiview2 : require\nlayout (num_views = 2) in;\n" + result;
|
|
|
}
|