【问题标题】:How do I include GLSL shader code in a seperate file to the main html? [duplicate]如何在单独的文件中将 GLSL 着色器代码包含到主 html 中? [复制]
【发布时间】:2018-08-26 17:03:18
【问题描述】:

我开始着手编写着色器,使用 THREE.js 构建 OpenGL 场景以使用用 GLSL 编写的着色器非常方便。到目前为止,我一直在主 HTML 文件的脚本字段中包含 GLSL 代码:

<html>
<head>
    <meta charset=uft-8>
    <title>Babby's first three.js app</title>
    <style>
        body { margin: 0; }
        canvas { width: 100%; height: 100% }
    </style>
</head>
<body>
    <script src="js/three.js"></script>

    <script id="fragShader" type="shader-code">
        // GLSL shader goes here!
        void main(){
            /* shader body */
        }
    </script>

    <script>
        // Three.js scene setup goes here

        // Get shader code from fragShader script element
        var shaderCode = document.getElementById("fragShader").innerHTML; 

        // Apply it to a material
        bufferMaterial = new THREE.ShaderMaterial({
            uniforms : {
                bufferTexture : {type : "t", value : textureA},
            },
            fragmentShader : shaderCode 
        });

        // Render everything
    </script>
</body> 

我正在处理一个更复杂的着色器项目,并希望将主 html 文件拆分,以便着色器代码可以单独保存,但我发现这很难做到。

我尝试使用 jquery 读取存储在单独文本文件中的着色器代码(我正在运行本地服务器):

<script src ="node_modules/jquery/dist/jquery.js"></script>
<script> 
    $(function(){
        $("#fragShader").load("mainShader.html"); // contains GLSL code
    });
</script> 

<script id="fragShader"></script>

但着色器无法编译 - fragment ERROR: Missing main()

非常感谢对这个 js 新手的任何帮助!

【问题讨论】:

    标签: javascript html three.js glsl


    【解决方案1】:

    我经常创建一个单独的 js 文件,它有一个表单对象:

    var customShaderObject = {
      fragmentShader: /* code (see below) */
      vertexShader: /* code (see below) */
      ... etc.
    }
    

    每个着色器都是一个字符串数组,每个索引代表一行,在末尾使用新行作为分隔符连接,例如

    fragmentShader: [
      'line 1',
      'line 2',
      'line 3',
      ' etc. '
    ].join('\r\n');
    

    就编辑代码而言,一种更简单的方法是使用模板文字语法(反引号`)而不是数组,因为这样您基本上可以像普通代码一样在多行上编辑单个字符串。

    这种方法(使用数组和模板字面量)还具有额外的优势,允许您将值创建为函数,以便您可以在运行时将变量插入到着色器的某些部分中,例如

    fragmentShader: function (bar) {
        return [
          'float foo = ' + bar.toString() + ';',
          'line 2',
          'line 3',
          ' etc. '
        ].join('\r\n');
      }
    

    或使用模板文字:

    fragmentShader: function (bar) {
        return `
          float foo = ${bar.toString()};
          line 2
          line 3
          //etc.
        `;
      }
    

    然后您可以通过引用它们的父对象来调用着色器,就像对任何其他 JS 对象一样。

    【讨论】:

    • 自 2009 年以来,除了 IE 之外的所有浏览器都可以使用模板文字。它们是 ES5 的一部分。不使用它们的理由为零。
    • 啊,感谢您指出这一点。我删除了对 ES6 的引用。但是,是的,应该使用它们 - 我认为如果像这些示例中那样使用它会更干净,更容易管理
    • THREE.FileLoader 也可用于异步获取着色器。
    猜你喜欢
    • 1970-01-01
    • 2014-11-19
    • 2017-09-20
    • 2015-08-16
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 2011-09-04
    相关资源
    最近更新 更多