如何将GLSL着色器代码包含在主html的单独文件中?

时间:2018-03-17 19:14:33

标签: javascript html three.js glsl

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

<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()

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

1 个答案:

答案 0 :(得分: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对象一样。