Вы спрашивали, как включить шейдеры как внешние файлы
Есть несколько способов, но сначала важно отметить, что использование обратных галочек для строк, которые называются multilineлитералы шаблона позволяют иметь многострочные строки
const str = `
this
string
is
on
multiple lines
`;
Так что нет необходимости использовать 'this' + 'that', как вы делали.
Если вы действительно хотитечтобы поместить их в отдельные файлы, тогда вот как минимум 3 из множества способов, которыми вы могли бы это сделать
поместить их в отдельные файлы сценариев, назначив их некоторым глобальным.Пример
vertexShader.js
window.shaders = window.shaders || {};
window.shaders.someVertexShader = `
attribute vec3 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 1.0);
gl_PointSize = 10.0;'
}
`;
в вашем html
<script src="vertexShader.js"></script>
<script>
// use shader as window.shaders.someVertexShader
...
</script>
Обратите внимание, что ваш окончательный сценарий JavaScript также может находиться в отдельном файле, если он имеетсяпосле файлов шейдеров.
Поместите их в отдельный модуль JavaScript
Современные браузеры поддерживают ES6-модули
vertexShader.js
export default `
attribute vec3 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 1.0);
gl_PointSize = 10.0;'
}
`;
В этом случае ваш скрипт JavaScript должен находиться во внешнем файле, чтобы ваш HTML мог выглядеть примерно так
<script src="main.js" type="module"></script>
и main.js будет выглядетькак-то так
import someVertexShader from './vertexShader.js';
// use someVertexShader
Вот пример здесь
Загрузите их с помощью fetch
В этом случае в файле шейдера нет JavaScript
vertexShader.shader
attribute vec3 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 1.0);
gl_PointSize = 10.0;'
}
Тогда в вашем скрипте
fetch('./vertexShader.shader')
.then(response => response.text())
.then((shaderSource) => {
// use shadeSource
});
Самая большая проблема с этим методомСценарии загружаются асинхронно, поэтому вам придется вручную ждать их загрузки.Однако использовать async / await довольно просто.
Представьте, что вы хотите загрузить 6 файлов шейдеров, а затем использовать их.Этот код будет ждать загрузки всех 6 файлов перед запуском
function loadTextFile(url) {
return fetch(url).then(response => response.text());
}
const urls = [
'./someShader1.shader',
'./someShader2.shader',
'./someShader3.shader',
'./someShader4.shader',
'./someShader5.shader',
'./someShader6.shader',
});
async function main() {
const files = await Promise.all(urls.map(loadTextFile));
// use files[0] thru files[5]
}
main();
Если бы это был я, и я действительно хотел бы поместить свои шейдеры во внешние файлы, я бы, вероятно, использовал import
и затем либо предназначаются только для современных браузеров, либо используют какую-либо программу, такую как webpack или rollup , чтобы упаковать их в один файл для отправки.Это то, что THREE.js делает в настоящее время.