2016-04-28 23 views
1

Meine HTML-Seite (pipad.org/tmp/fourier02.html) enthält zwei Shadern:Vermeidung von Code-Duplizierung für eine Funktion geteilt zwischen zwei GLSL Shadern

<script type="application/glsl" id="shaderA"> 
    uniform vec4 a; 
    vec4 f(vec4 x, vec4 y){ ... } // DUP 
    vec4 main(vec4 u, vec4 v) { return f(a,u); } 
</script> 

<script type="application/glsl" id="shaderB"> 
    uniform vec4 a; 
    vec4 f(vec4 x, vec4 y){ ... } // DUP 
    vec4 main(vec4 u) { return f(a,u); } // notice main's sig is different 
</script> 

ich hoffe ich bin nicht zu stark zu vereinfachen, kann ich zu überarbeiten, wenn ich es bin. Diese Shader werden auf verschiedene Arten verwendet (ShaderB ist RTT).

Wie man sieht, ist f in beiden Fällen identisch.

Gibt es eine Möglichkeit zu vermeiden, es zweimal zu schreiben?

Der einzige Weg, ich sehe die Shadern als Strings hält, was unordentlich ist, weil Syntax nicht mehr hervorheben funktioniert und was Sie tun müssen:

: 
var 
f = 
    "vec4 f(vec4 x, vec4 y){\n" + 
    "...\n" + 
    "}\n", 

shaderA = f + 
    "uniform vec4 a;\n" + 
    "vec4 main(vec4 u, vec4 v) { return f(a,u); }\n", 

shaderB = f + 
    "uniform vec4 a;\n" + 
    "vec4 main(vec4 u) { return f(a,u); }\n" 
; 

usw.

das ist ... meh. Kein klarer Vorteil gegenüber dem Original. Wir haben gerade die Duplikation gegen Ickness ausgetauscht.

Gibt es einen besseren Weg?

Antwort

2

Wie Sie bereits gefunden haben, String-Manipulation ist eine gebräuchliche Art, Shader zu erstellen. So ziemlich alle großen Engines verwenden viele String-Ersetzungen, um Shader zur Laufzeit zu erstellen. WaclawJasper wies auf Template-Strings hin. Sie sind ein neues Feature von JavaScript, aber da nahezu alle Browser, die WebGL unterstützen, regelmäßige Updates erhalten, können Sie diese wahrscheinlich dann ziemlich sicher verwenden, oder Sie können einen Polyfill verwenden.

Beispiel

var t = { 
 
    PI: '3.14159', 
 
    plusToPlusMinus: ` 
 
    float plusToPlusMinus(float v) { 
 
     return v * 2.0 - 1.0; 
 
    } 
 
    `, 
 
}; 
 

 
var shader = ` 
 
    ${t.plusToPlusMinus} 
 
    ... 
 
    void main() { 
 
    a = b * ${t.PI}; 
 
    } 
 
`; 
 

 
console.log(shader);

Ausgänge:

float plusToPlusMinus(float v) { 
    return v * 2.0 - 1.0; 
    } 

... 
void main() { 
a = b * 3.14159; 
} 
1

Klingt nach dem, was Sie suchen, ist template strings. Es unterstützt standardmäßig mehrzeilige Strings.

Wenn Kompatibilität ein Problem ist, ist shader = ["blah", "blah"].join('\n'); IMO sauberer als String-Verkettung.

1

Am Ende zog ich meine gemeinsame Funktion zu einem separaten <script type="application/glsl" id="common"> Tag und tat

<script> 
    : 
    function joinElements(A,B) { 
     return document.getElementById(A).innerHTML 
      + document.getElementById(B).innerHTML; 
    } 
    : 

... und ersetzt dann "#shaderA" mit joinElements("#common", "shaderA");