Javascript и WebGL, внешние скрипты - PullRequest
25 голосов
/ 02 февраля 2011

Просто любопытно; Как поместить мои шейдеры webgl во внешний файл?

В настоящее время у меня;

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

В моем html-заголовке, как мне связать это из внешнего файла? - Я попробовал обычный подход JavaScript;

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

Ответы [ 4 ]

23 голосов
/ 03 февраля 2011

Для внешних файлов вам необходимо прекратить использование тега script. Я предлагаю использовать что-то вроде XMLHttpRequest . Я бы также предложил переименовать ваши файлы, они являются шейдерами, а не Javascript, поэтому используйте другое расширение, чтобы избежать путаницы. Я использую что-то вроде "iny_surface.shader ".

Вот что я делаю:

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 + '"');
}); 

Если вы используете библиотеку, такую ​​как JQuery, у них, вероятно, есть функция, аналогичная моей loadFiles.

5 голосов
/ 19 сентября 2011

У меня была такая же проблема, и я обнаружил, что это работает для меня с 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();
       });
});   

Где shader.fs и shader.vs - мои шейдеры (включая
<script type="x-shader/x-fragment"> и <script type="x-shader/x-vertex"> строк объявления)

Обновление С 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'
        });               

Обновление 2: Поскольку < и & в источнике шейдера необходимо экранировать для загрузки в виде XML, это работает постоянно, даже если вы используете операторы less than сравнения или логические операторы и:

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'
});
0 голосов
/ 25 ноября 2013

Вы можете использовать библиотеку управления шейдерами с открытым исходным кодом, такую ​​как моя:

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

Позволяет загружать шейдеры из URL-адресов и кэшировать исходный код шейдера для будущих посещений сайта. Это также упрощает использование униформы.

0 голосов
/ 08 февраля 2011

Я не гуру WebGL, но работает ли это?

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