├── dist ├── assets │ ├── kv.jpg │ ├── kv.psd │ ├── og.jpg │ ├── og.psd │ ├── og2.jpg │ ├── icon.png │ ├── icon.psd │ ├── icon2.png │ ├── icon2.psd │ └── icons.psd ├── fv │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── mstile-150x150.png │ ├── apple-touch-icon.png │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── browserconfig.xml │ ├── site.webmanifest │ └── safari-pinned-tab.svg ├── css │ ├── styles.css │ └── themes │ │ ├── glslrun-dark.css │ │ └── gruvbox-dark.css └── index.html ├── src ├── print.js ├── index.js ├── swizzles.js ├── editor.js └── commands.js ├── package.json ├── webpack.config.js └── README.md /dist/assets/kv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/kv.jpg -------------------------------------------------------------------------------- /dist/assets/kv.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/kv.psd -------------------------------------------------------------------------------- /dist/assets/og.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/og.jpg -------------------------------------------------------------------------------- /dist/assets/og.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/og.psd -------------------------------------------------------------------------------- /dist/assets/og2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/og2.jpg -------------------------------------------------------------------------------- /dist/fv/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/fv/favicon.ico -------------------------------------------------------------------------------- /dist/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/icon.png -------------------------------------------------------------------------------- /dist/assets/icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/icon.psd -------------------------------------------------------------------------------- /dist/assets/icon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/icon2.png -------------------------------------------------------------------------------- /dist/assets/icon2.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/icon2.psd -------------------------------------------------------------------------------- /dist/assets/icons.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/assets/icons.psd -------------------------------------------------------------------------------- /dist/fv/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/fv/favicon-16x16.png -------------------------------------------------------------------------------- /dist/fv/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/fv/favicon-32x32.png -------------------------------------------------------------------------------- /dist/fv/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/fv/mstile-150x150.png -------------------------------------------------------------------------------- /dist/fv/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/fv/apple-touch-icon.png -------------------------------------------------------------------------------- /dist/fv/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/fv/android-chrome-192x192.png -------------------------------------------------------------------------------- /dist/fv/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iY0Yi/GLSLRun/HEAD/dist/fv/android-chrome-512x512.png -------------------------------------------------------------------------------- /dist/fv/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #000000 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/print.js: -------------------------------------------------------------------------------- 1 | // Define the print function 2 | // --------------------------------------------------------------- 3 | export default function print(){ 4 | let str = Array.prototype.join.call(arguments, " "); 5 | console.log(str); 6 | let span = document.createElement('span'); 7 | span.textContent = str + "\n"; 8 | txtAnsw.appendChild(span); 9 | } 10 | window.print = print -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import key from 'keymaster' 2 | 3 | import {Swizzles} from './swizzles' 4 | import {print} from './print' 5 | import {Editor} from './editor' 6 | import {Commands} from './commands' 7 | 8 | Swizzles.init() 9 | Editor.init() 10 | 11 | document.getElementById('btnRun').addEventListener('click', Commands.run) 12 | key.filter = function(event){return true} 13 | key('⌥+enter', Commands.run) 14 | key.setScope('default') -------------------------------------------------------------------------------- /dist/fv/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GLSLRun", 3 | "short_name": "GLSLRun", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#000000", 17 | "background_color": "#000000", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tutorial-optimize", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "build": "webpack", 6 | "start": "webpack serve" 7 | }, 8 | "devDependencies": { 9 | "webpack": "^5.88.2", 10 | "webpack-cli": "^5.1.4", 11 | "webpack-dev-server": "^4.15.1" 12 | }, 13 | "private": true, 14 | "dependencies": { 15 | "assert": "^2.0.0", 16 | "codemirror": "^5.65.14", 17 | "glsl-transpiler": "^2.0.1", 18 | "keymaster": "^1.6.2", 19 | "process": "^0.11.10", 20 | "stream": "^0.0.2" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | module.exports = { 3 | entry: `./src/index.js`, 4 | 5 | output: { 6 | filename: "main.js" 7 | }, 8 | mode: "development", 9 | resolve: { 10 | fallback: { 11 | "assert": require.resolve("assert"), 12 | } 13 | }, 14 | devServer: { 15 | static: "dist", 16 | open: true 17 | }, 18 | plugins: [ 19 | // fix "process is not defined" error: 20 | new webpack.ProvidePlugin({ 21 | process: 'process/browser', 22 | }), 23 | ] 24 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GLSLRun 2 |
3 |
4 | GLSLRun is a tool that allows you to insert print() into short GLSL code for debugging. 5 | But this is under development. 6 | Pull requests are welcome :)
7 |
8 | 9 | ## App 10 | https://glslrun.xyz/ 11 | 12 | ## Development 13 | - ```npm install``` 14 | - ```npm run start``` 15 | - access: http://localhost:8080/
16 |
17 | 18 | ## Dependencies 19 | [Codemirror](https://github.com/codemirror/CodeMirror)
20 | [glsl-transpiler](https://github.com/stackgl/glsl-transpiler)
21 |
22 | 23 | ## Contact 24 | [iY0Yi](https://twitter.com/iY0Yi/)
25 |
26 | -------------------------------------------------------------------------------- /dist/fv/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /dist/css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #3c3836; 3 | color: #bdae93; 4 | font-family: 'Mulish', sans-serif; 5 | margin: 0px; 6 | width: 100vw; 7 | } 8 | 9 | .CodeMirror{ 10 | font-size: 13pt; 11 | } 12 | .CodeMirror-lines{ 13 | font-family: 'Overpass Mono', monospace; 14 | font-weight: 300; 15 | } 16 | 17 | .CodeMirror-vscrollbar { 18 | display: none !important; 19 | } 20 | 21 | #footer { 22 | bottom: 0; 23 | width: 100vw; 24 | height: 300px; 25 | color: #131614; /* gruvbox light foreground */ 26 | overflow: hidden; 27 | } 28 | 29 | #txtAnsw { 30 | font-family: 'Overpass Mono', monospace; 31 | font-weight: 400; 32 | background-color: #002b16; 33 | border-radius: 0px; 34 | color: #00b600; 35 | border: none; 36 | margin: 0px; 37 | padding: 10px 10px; 38 | width: calc(100% - 20px); 39 | padding-bottom: 0px; 40 | height: calc(100% - 10px); 41 | font-size: 13pt; 42 | overflow-x: hidden; 43 | overflow-y: scroll; 44 | } 45 | 46 | #txtAnsw::-webkit-scrollbar{ 47 | display: none; 48 | } 49 | 50 | #errorText{ 51 | color: #d81d00; 52 | } 53 | 54 | #btnRun { 55 | position: absolute; 56 | right: 20px; 57 | bottom: 20px; 58 | background-color: #00ff00; 59 | color: #282828; 60 | border: none; 61 | cursor: pointer; 62 | padding: 10px 20px 12px 20px; 63 | border-radius: 30px; 64 | font-size: 12pt; 65 | font-weight: 600; 66 | text-align: center; 67 | width: 60px; 68 | user-select: none; 69 | } 70 | 71 | #btnRun:hover { 72 | background-color: #6aff9e; 73 | } 74 | -------------------------------------------------------------------------------- /src/swizzles.js: -------------------------------------------------------------------------------- 1 | // Build swizzles on Array object 2 | // --------------------------------------------------------------- 3 | function buildSwizzleCombos(maxLength, components = ['x', 'y', 'z', 'w'], current = '', swizzles = []) { 4 | if (current.length >= maxLength) return swizzles 5 | for (let component of components) { 6 | let newSwizzle = current + component 7 | swizzles.push(newSwizzle) 8 | buildSwizzleCombos(maxLength, components, newSwizzle, swizzles) 9 | } 10 | return swizzles 11 | } 12 | 13 | const swXYZW = buildSwizzleCombos(4, ['x', 'y', 'z', 'w']) 14 | const swRGBA = buildSwizzleCombos(4, ['r', 'g', 'b', 'a']) 15 | 16 | export let Swizzles = { 17 | init: function(){ 18 | for (let sw of swXYZW) { 19 | Object.defineProperty(Array.prototype, sw, { 20 | get: function() { 21 | return sw.split('').map(c => { 22 | switch (c) { 23 | case 'x': return this[0] 24 | case 'y': return this[1] 25 | case 'z': return this[2] 26 | case 'w': return this[3] 27 | default: return undefined 28 | } 29 | }) 30 | } 31 | }) 32 | } 33 | 34 | for (let sw of swRGBA) { 35 | Object.defineProperty(Array.prototype, sw, { 36 | get: function() { 37 | return sw.split('').map(c => { 38 | switch (c) { 39 | case 'r': return this[0] 40 | case 'g': return this[1] 41 | case 'b': return this[2] 42 | case 'a': return this[3] 43 | default: return undefined 44 | } 45 | }) 46 | } 47 | }) 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /dist/css/themes/glslrun-dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Name: glslrun-dark 4 | Author: iY0Yi (https://github.com/krkk) 5 | Original glslrun color scheme by iY0Yi 6 | 7 | */ 8 | 9 | .cm-s-glslrun-dark.CodeMirror, .cm-s-glslrun-dark .CodeMirror-gutters { background-color: #001700; color: #14b114; } 10 | .cm-s-glslrun-dark .CodeMirror-gutters {background: #001700; border-right: 0px;} 11 | .cm-s-glslrun-dark .CodeMirror-linenumber {color: #005c00;} 12 | .cm-s-glslrun-dark .CodeMirror-cursor { border-left: 1px solid #00ff00; } 13 | .cm-s-glslrun-dark.cm-fat-cursor .CodeMirror-cursor { background-color: #8e8d8875 !important; } 14 | .cm-s-glslrun-dark .cm-animate-fat-cursor { background-color: #8e8d8875 !important; } 15 | .cm-s-glslrun-dark div.CodeMirror-selected { background: #007b00; } 16 | .cm-s-glslrun-dark span.cm-meta { color: #83a598; } 17 | 18 | .cm-s-glslrun-dark span.cm-comment { color: #007700; } 19 | .cm-s-glslrun-dark span.cm-number, span.cm-atom { color: #d2ffdf; } 20 | .cm-s-glslrun-dark span.cm-keyword { color: #00ff00; } 21 | 22 | .cm-s-glslrun-dark span.cm-variable { color: #b2ebdd; } 23 | .cm-s-glslrun-dark span.cm-variable-2 { color: #b2ebdd; } 24 | .cm-s-glslrun-dark span.cm-variable-3, .cm-s-glslrun-dark span.cm-type { color: #00ffbb; } 25 | .cm-s-glslrun-dark span.cm-operator { color: #b2ebe4; } 26 | .cm-s-glslrun-dark span.cm-callee { color: #b2ebc1; } 27 | .cm-s-glslrun-dark span.cm-def { color: #b2ebb6; } 28 | .cm-s-glslrun-dark span.cm-property { color: #b2ebbb; } 29 | .cm-s-glslrun-dark span.cm-string { color: #7acdbd; } 30 | .cm-s-glslrun-dark span.cm-string-2 { color: #8ec07c; } 31 | .cm-s-glslrun-dark span.cm-qualifier { color: #8ec07c; } 32 | .cm-s-glslrun-dark span.cm-attribute { color: #8ec07c; } 33 | 34 | .cm-s-glslrun-dark .CodeMirror-activeline-background { background: #112510; } 35 | .cm-s-glslrun-dark .CodeMirror-matchingbracket { background: #006a38; color:#092411 !important; } 36 | 37 | .cm-s-glslrun-dark span.cm-builtin { color: #00ff00; } 38 | .cm-s-glslrun-dark span.cm-tag { color: #00ff00; } -------------------------------------------------------------------------------- /src/editor.js: -------------------------------------------------------------------------------- 1 | import CodeMirror from 'codemirror/lib/codemirror' 2 | import 'codemirror/keymap/sublime' 3 | import 'codemirror/mode/clike/clike' 4 | export let Editor = { 5 | cm: null, 6 | init: function(){ 7 | const divEditor = document.getElementById('glslEditor') 8 | this.cm = CodeMirror(divEditor, { 9 | lineNumbers: true, 10 | matchBrackets: true, 11 | mode: 'x-shader/x-fragment', 12 | theme: "glslrun-dark", 13 | fontSize: '26pt', 14 | cursorBlinkRate: 530, 15 | smartIndent: true, 16 | indentWithTabs: false, 17 | indentUnit: 4, 18 | showInvisibles: true, 19 | maxInvisibles: 16, 20 | keyMap: 'sublime', 21 | styleActiveLine: true, 22 | styleSelectedText: true, 23 | styleCursor: true, 24 | autoCloseBrackets: false, 25 | matchBrackets: true, 26 | showCursorWhenSelecting: true, 27 | selectionPointer: true, 28 | autofocus: true, 29 | continuousScanning: 500, 30 | foldGutter: true 31 | }) 32 | this.cm.setSize(null, '600px') 33 | this.cm.getDoc().setValue(`#define PI acos(-1.); 34 | for(float i=0.; i<200.; i++){ 35 | float a = i/200.*PI; 36 | vec2 v = vec2(sin(a), cos(a)); 37 | print(v); 38 | }`) 39 | 40 | // Adjust the editor's height 41 | function adjustEditorHeight(){ 42 | const footerHeight = document.getElementById('footer').offsetHeight 43 | const windowHeight = window.innerHeight 44 | Editor.cm.setSize(null, `${windowHeight - footerHeight}px`) 45 | } 46 | 47 | // Initial adjustment 48 | adjustEditorHeight() 49 | // Adjust the editor's height whenever the window is resized 50 | window.addEventListener('resize', adjustEditorHeight) 51 | }, 52 | getCode: function(){ 53 | return this.cm.getValue() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /dist/css/themes/gruvbox-dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Name: gruvbox-dark 4 | Author: kRkk (https://github.com/krkk) 5 | 6 | Original gruvbox color scheme by Pavel Pertsev (https://github.com/morhetz/gruvbox) 7 | 8 | */ 9 | 10 | .cm-s-gruvbox-dark.CodeMirror, .cm-s-gruvbox-dark .CodeMirror-gutters { background-color: #282828; color: #bdae93; } 11 | .cm-s-gruvbox-dark .CodeMirror-gutters {background: #282828; border-right: 0px;} 12 | .cm-s-gruvbox-dark .CodeMirror-linenumber {color: #7c6f64;} 13 | .cm-s-gruvbox-dark .CodeMirror-cursor { border-left: 1px solid #ebdbb2; } 14 | .cm-s-gruvbox-dark.cm-fat-cursor .CodeMirror-cursor { background-color: #8e8d8875 !important; } 15 | .cm-s-gruvbox-dark .cm-animate-fat-cursor { background-color: #8e8d8875 !important; } 16 | .cm-s-gruvbox-dark div.CodeMirror-selected { background: #928374; } 17 | .cm-s-gruvbox-dark span.cm-meta { color: #83a598; } 18 | 19 | .cm-s-gruvbox-dark span.cm-comment { color: #928374; } 20 | .cm-s-gruvbox-dark span.cm-number, span.cm-atom { color: #d3869b; } 21 | .cm-s-gruvbox-dark span.cm-keyword { color: #f84934; } 22 | 23 | .cm-s-gruvbox-dark span.cm-variable { color: #ebdbb2; } 24 | .cm-s-gruvbox-dark span.cm-variable-2 { color: #ebdbb2; } 25 | .cm-s-gruvbox-dark span.cm-variable-3, .cm-s-gruvbox-dark span.cm-type { color: #fabd2f; } 26 | .cm-s-gruvbox-dark span.cm-operator { color: #ebdbb2; } 27 | .cm-s-gruvbox-dark span.cm-callee { color: #ebdbb2; } 28 | .cm-s-gruvbox-dark span.cm-def { color: #ebdbb2; } 29 | .cm-s-gruvbox-dark span.cm-property { color: #ebdbb2; } 30 | .cm-s-gruvbox-dark span.cm-string { color: #b8bb26; } 31 | .cm-s-gruvbox-dark span.cm-string-2 { color: #8ec07c; } 32 | .cm-s-gruvbox-dark span.cm-qualifier { color: #8ec07c; } 33 | .cm-s-gruvbox-dark span.cm-attribute { color: #8ec07c; } 34 | 35 | .cm-s-gruvbox-dark .CodeMirror-activeline-background { background: #3c3836; } 36 | .cm-s-gruvbox-dark .CodeMirror-matchingbracket { background: #928374; color:#282828 !important; } 37 | 38 | .cm-s-gruvbox-dark span.cm-builtin { color: #fe8019; } 39 | .cm-s-gruvbox-dark span.cm-tag { color: #fe8019; } -------------------------------------------------------------------------------- /src/commands.js: -------------------------------------------------------------------------------- 1 | import GLSL from 'glsl-transpiler' 2 | import {Editor} from './editor' 3 | export let Commands = { 4 | run: function(){ 5 | let glslCode = Editor.getCode() 6 | const glslLines = glslCode.split('\n') 7 | const printLines = {} 8 | 9 | // Hack: Replace print function calls in GLSL code 10 | for (let i = 0; i < glslLines.length; i++) { 11 | if (glslLines[i].includes('print')) { 12 | printLines['print' + i] = glslLines[i] 13 | glslLines[i] = 'float print' + i + ' = 0.;' 14 | } 15 | } 16 | glslCode = glslLines.join('\n') 17 | const transpiler = GLSL({}) 18 | let transpiledJsCode 19 | 20 | try { 21 | transpiledJsCode = transpiler(glslCode) 22 | } catch (error) { 23 | console.error(error) 24 | transpiledJsCode = 'Error in transpiling GLSL to JavaScript: ' + error.message 25 | } 26 | 27 | let transpiledJsLines = transpiledJsCode.split('\n') 28 | 29 | // Hack: Replace print function calls in transpiled JavaScript code 30 | for (let i = 0; i < transpiledJsLines.length; i++) { 31 | if (transpiledJsLines[i].includes('print')) { 32 | transpiledJsLines[i] = printLines[transpiledJsLines[i].split(' ')[1]] 33 | } 34 | } 35 | transpiledJsCode = transpiledJsLines.join('\n') 36 | 37 | // Try to evaluate the transpiled JavaScript code 38 | let span = document.createElement('span') 39 | try { 40 | eval(transpiledJsCode) 41 | span.textContent = '\n' 42 | } catch (error) { 43 | let str = 'Error in transpiling GLSL to JavaScript:\n ' + error.message + '\n' 44 | str += ' '+transpiledJsCode.replace('Error in transpiling GLSL to JavaScript: ', '') + '\n\n' 45 | console.error(str) 46 | span.id = 'errorText' 47 | span.textContent = str 48 | } 49 | txtAnsw.appendChild(span) 50 | Commands.autoScroll() 51 | }, 52 | 53 | autoScroll: function(){ 54 | const txtAnsw = document.getElementById('txtAnsw') 55 | txtAnsw.scrollTop = txtAnsw.scrollHeight 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | GLSLRun 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 54 | 55 | 56 | 57 | --------------------------------------------------------------------------------