Javascript 和 WebGL,外部脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4878145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 15:12:29  来源:igfitidea点击:

Javascript and WebGL, external scripts

javascriptexternalexternwebglopengl-es-2.0

提问by Skeen

Just curious; How do I place my webgl shaders, in an external file?

只是好奇; 如何将我的 webgl 着色器放置在外部文件中?

Currently I'm having;

目前我有;

    <script id="shader-fs" type="x-shader/x-fragment">
        #ifdef GL_ES
            precision highp float;
        #endif

        void main(void)
        {
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    </script>

    <script id="shader-vs" type="x-shader/x-vertex">
        attribute vec3 aVertexPosition;

        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;

        void main(void)
        {
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
        }
    </script>

In my html header, how do I link in this from an external file? - I tried the usual javascript approach;

在我的 html 标头中,我如何从外部文件链接到这个?- 我尝试了通常的 javascript 方法;

<script type="text/javascript" src="webgl_shader.js"></script>

采纳答案by David Roe

For external files, you need to stop using the script tag. I suggest using something like XMLHttpRequest. I would also suggest renaming your files, they are shaders not Javascript so use a different extension to avoid confusion. I use something like "shiny_surface.shader".

对于外部文件,您需要停止使用脚本标签。我建议使用类似XMLHttpRequest 的东西。我还建议重命名您的文件,它们是着色器而不是 Javascript,因此请使用不同的扩展名以避免混淆。我使用类似“shiny_surface.shader”的东西。

This is what I do:

这就是我所做的:

function loadFile(url, data, callback, errorCallback) {
    // Set up an asynchronous request
    var request = new XMLHttpRequest();
    request.open('GET', url, true);

    // Hook the event that gets called as the request progresses
    request.onreadystatechange = function () {
        // If the request is "DONE" (completed or failed)
        if (request.readyState == 4) {
            // If we got HTTP status 200 (OK)
            if (request.status == 200) {
                callback(request.responseText, data)
            } else { // Failed
                errorCallback(url);
            }
        }
    };

    request.send(null);    
}

function loadFiles(urls, callback, errorCallback) {
    var numUrls = urls.length;
    var numComplete = 0;
    var result = [];

    // Callback for a single file
    function partialCallback(text, urlIndex) {
        result[urlIndex] = text;
        numComplete++;

        // When all files have downloaded
        if (numComplete == numUrls) {
            callback(result);
        }
    }

    for (var i = 0; i < numUrls; i++) {
        loadFile(urls[i], i, partialCallback, errorCallback);
    }
}

var gl;
// ... set up WebGL ...

loadFiles(['vertex.shader', 'fragment.shader'], function (shaderText) {
    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, shaderText[0]);
    // ... compile shader, etc ...
    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, shaderText[1]);

    // ... set up shader program and start render loop timer
}, function (url) {
    alert('Failed to download "' + url + '"');
}); 

If you're using a library like JQuery, they probably have a function similar to my loadFiles one.

如果你使用像 JQuery 这样的库,它们可能有一个类似于我的 loadFiles 的函数。

回答by brian_d

I had the same issue and found that this has worked for me with jQuery:

我有同样的问题,发现这对我有用 jQuery:

var fragmentShaderSRC = null,
var vertexShaderSRC = null;
...
function executeProgram(){ //main program }
...
$.get("shader.fs", function(data){ 
       fragmentShaderSRC = data.firstChild.textContent;
       $.get("shader.vs", function(data){
             vertexShaderSRC = data.firstChild.textContent;
             executeProgram();
       });
});   

Where shader.fsand shader.vsare my shaders (and include the
<script type="x-shader/x-fragment">and <script type="x-shader/x-vertex">declaration lines)

shader.fsshader.vs是我的着色器(以及包括
<script type="x-shader/x-fragment"><script type="x-shader/x-vertex">报关行)

UpdateWith Chrome the intelligent guess does not select 'xml'. The following code works in Chrome as well:

使用 Chrome更新智能猜测不会选择“xml”。以下代码也适用于 Chrome:

$.ajax({
          url: 'shader.fs', 
          success: function(data){ 
              fragmentShaderSRC = data.firstChild.textContent;
              $.ajax({
                  url: 'shader.vs', 
                  success: function(data){
                      vertexShaderSRC = data.firstChild.textContent;
                      executeProgram();
                   },
                   dataType: 'xml'
              })
           },
           dataType: 'xml'
        });               

Update 2:As <and &in the shader source need to be escaped to load in as XML, this works all of the time even if you use the less than comparision or the and logic operators:

更新 2:因为<&在着色器源中需要转义以作为 XML 加载,即使您使用小于比较或逻辑运算符,这也一直有效:

var vs_source = null,
    fs_source = null;
$.ajax({
    async: false,
    url: './my_shader.vs',
    success: function (data) {
        vs_source = $(data).html();
    },
    dataType: 'html'
});

$.ajax({
    async: false,
    url: './my_shader.fs',
    success: function (data) {
        fs_source = $(data).html();
    },
    dataType: 'html'
});

回答by ILOVEPIE

You could use an open source shader managing library like mine:

您可以使用像我这样的开源着色器管理库:

https://github.com/ILOVEPIE/Shader.js

https://github.com/ILOVEPIE/Shader.js

It lets you load shaders from urls and caches shader source code for future visits to the site. It also makes it simpler to use uniforms.

它允许您从 url 加载着色器并缓存着色器源代码以供将来访问该站点。它还使使用制服变得更简单。

回答by Arne Bergene Fossaa

I am no WebGL guru, but does this work?

我不是 WebGL 专家,但这行得通吗?

<script id="shader-fs" type="x-shader/x-fragment" src="fragment-shader.fs" />