Javascript и WebGL, внешние скрипты
Просто любопытно; Как поместить мои шейдеры 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>
Ответы
Ответ 1
Для внешних файлов вам необходимо прекратить использование тега script. Я предлагаю использовать что-то вроде XMLHttpRequest. Я бы также предложил переименовать ваши файлы, они шейдеры, а не Javascript, поэтому используйте другое расширение, чтобы избежать путаницы. Я использую что-то вроде "shiny_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.
Ответ 2
У меня была такая же проблема и я обнаружил, что это сработало для меня с 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, это работает все время, даже если вы используете менее сравнительные или логические операторы:
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'
});
Ответ 3
Вы можете использовать библиотеку управления шейдером с открытым исходным кодом, например my:
https://github.com/ILOVEPIE/Shader.js
Он позволяет загружать шейдеры из URL-адресов и кешировать исходный код шейдера для будущих посещений сайта.
Это также упрощает использование униформ.
Ответ 4
Я не гуру WebGL, но работает ли это?
<script id="shader-fs" type="x-shader/x-fragment" src="fragment-shader.fs" />