GLSL to WGSL converter (using TintWASM)
Convert from GLSL to WGSL using the WASM version of the Tint library
by cx20
HTML
<script src="https://cx20.github.io/webgpu-test/libs/glslang.js"></script>
<!-- see: https://forum.babylonjs.com/t/can-i-use-the-tintwasm-library-in-the-babylon-js-repository/23673 -->
<script src="https://cx20.github.io/webgpu-test/libs/twgsl.js"></script>
<script src="https://rawcdn.githack.com/codemirror/CodeMirror/v3.12/lib/codemirror.js"></script>
<script src="https://rawcdn.githack.com/codemirror/CodeMirror/v3.12/mode/clike/clike.js"></script>
<script src="https://rawcdn.githack.com/codemirror/CodeMirror/v3.12/mode/rust/rust.js"></script>
<select name="shader_type" id="shader_type">
<option value="vertex">vertex</option>
<option value="fragment">fragment</option>
</select>
<div><textarea id="glsl" name="glsl">
#version 450
layout(location = 0) in vec3 position;
void main() {
gl_Position = vec4(position, 1.0);
}
</textarea></div>
<input type="button" id="convert" value="Convert GLSL to WGSL" />
<div><textarea id="wgsl" name="wgsl"></textarea></div>
CSS
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: auto;
}
.CodeMirror-scroll {
/* Set scrolling behaviour here */
overflow: auto;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
}
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black;
z-index: 3;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
z-index: 1;
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
.cm-tab { display: inline-block; }
/* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable {color: black;}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-property {color: black;}
.cm-s-default .cm-operator {color: black;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-error {color: #f00;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color:...
JavaScript
const VERTEX_SHADER_SAMPLE = `#version 450
layout(location = 0) in vec3 position;
void main() {
gl_Position = vec4(position, 1.0);
}
`;
const FRAGMENT_SHADER_SAMPLE = `#version 450
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(0.0, 0.0, 1.0, 1.0);
}
`;
let libGlslang = null;
let libTwgsl = null;
let promise1 = glslang();
let promise2 = twgsl("https://cx20.github.io/webgpu-test/libs/twgsl.wasm");
Promise.all([promise1, promise2]).then((args) => {
libGlslang = args[0];
libTwgsl = args[1];
});
let editorGLSL = CodeMirror.fromTextArea(document.getElementById("glsl"), {
lineNumbers: true,
matchBrackets: true,
autofocus: true,
mode: "text/x-csrc"
});
let editorWGSL = CodeMirror.fromTextArea(document.getElementById("wgsl"), {
lineNumbers: true,
matchBrackets: true,
autofocus: true,
mode: "text/x-rustsrc"
});
let selectBox = document.getElementById('shader_type');
let convertButton = document.getElementById('convert');
selectBox.addEventListener('change', changeShaderType);
convertButton.addEventListener('click', convertGlslToWgsl);
function changeShaderType() {
switch (selectBox.value) {
case "vertex":
editorGLSL.doc.setValue(VERTEX_SHADER_SAMPLE);
break;
case "fragment":
editorGLSL.doc.setValue(FRAGMENT_SHADER_SAMPLE);
break;
}
editorWGSL.doc.setValue("");
}
function convertGlslToWgsl() {
let glslCode = editorGLSL.doc.getValue();
let type = selectBox.value;
let spirv = libGlslang.compileGLSL(glslCode, type);
let wgslCode = libTwgsl.convertSpirV2WGSL(spirv);
editorWGSL.doc.setValue(wgslCode);
}