Dov*_*Dov 24 javascript glsl webgl three.js
我见过以下问题,有人问如何从html中删除着色器: WebGL - 是否有在HTML中嵌入着色器的替代方法?
有一些精心设计的解决方法可以加载到包含问题答案中建议的着色器的文件中.
在我看到的教程中,着色器代码直接嵌入在html中.javascript代码使用getElementById引用它.但由于很多原因,将着色器直接嵌入到html中很难看.为什么我不能使用src =属性在外部引用它?
<script type="x-shader/x-fragment" id="shader-fs" src="util/fs"></script>
Run Code Online (Sandbox Code Playgroud)
以上不起作用,我只想知道为什么不行.这显然与脚本本身的限制有关,但我不明白.
Phi*_*ipp 33
您根本不必使用<script>标记来加载着色器程序.大多数教程和示例只是将它们用作容器来将字符串存储在网页的DOM中.脚本类型"x-shader/x-fragment"对于Web浏览器没有意义,因此它们不执行脚本.但是,它们会将该标记的内容作为字符串存储在DOM中,以后可以通过"真实"脚本进行访问.这仅在脚本内容位于HTML文件中时才有效.通过src属性加载脚本时,内容不会成为脚本标记的文本子节点,因此无法通过DOM树访问.
您也可以将着色器的源代码存储为Javascript文件中的字符串:
// myVertextShader.glsl.js
var myVertexShaderSrc =
"attribute vec3 pos;"+
"void main() {"+
" gl_Position = vec4(pos, 1.0);"+
"}"
;
Run Code Online (Sandbox Code Playgroud)
然后你会像这样编译着色器:
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, myVertexShaderSrc);
gl.compileShader(vertexShader);
gl.attachShader(program, vertexShader);
Run Code Online (Sandbox Code Playgroud)
gma*_*man 27
在2018年,我建议使用多行模板文字,如在带有反引号的着色器环绕中,它可以跨越多行
const someShaderSource = `
attribute vec4 position;
uniform mat4 matrix;
void main() {
gl_Position = matrix * position;
}
`;
Run Code Online (Sandbox Code Playgroud)
如果要将着色器放在单独的文件中,可以使用JavaScript模块在2018年轻松完成.着色器文件可能如下所示
// someshader.glsl.js
export default `
attribute vec4 position;
uniform mat4 matrix;
void main() {
gl_Position = matrix * position;
}
`;
Run Code Online (Sandbox Code Playgroud)
要使用JavaScript模块,您的主JavaScript必须位于单独的文件中.您可以通过导入来访问着色器源
// main.js
import someShaderSource from './someshader.glsl.js';
// use someShadeSource
Run Code Online (Sandbox Code Playgroud)
并将其包含在HTML中
<script src="main.js" type="module"></script>
Run Code Online (Sandbox Code Playgroud)
如果您想支持旧版浏览器,可以使用汇总等工具来读取所有import语句并生成一个大型JavaScript文件.这就是three.js所做的.
如果您需要支持IE11,您可以使用babel转换多行模板.多年来,所有其他浏览器都支持多行模板.
为什么着色器必须在web文件程序的html文件中?
他们没有
您可以将着色器放在外部JavaScript中.例如
<script type="module">
import someShaderSource from './someshader.glsl.js';
// use someShadeSource
</script>
Run Code Online (Sandbox Code Playgroud)
或另一种常见格式
// --myshader.js--
var myFragmentShader =
"void main() {\n" +
" gl_FragColor = vec4(1,0,0,1);\n" +
"}n\";
Run Code Online (Sandbox Code Playgroud)
在支持WebGL的所有浏览器中,您都可以使用模板文字
// --myshader.js--
var myFragmentShader = [
"void main() {",
" gl_FragColor = vec4(1,0,0,1);",
"}",
].join("\n");
Run Code Online (Sandbox Code Playgroud)
否则,您可以将它们放在文本文件中并使用XMLHTTPRequest加载它们
// --myshader.js--
var myFragmentShader = `
void main() {
gl_FragColor = vec4(1,0,0,1);
}
`;
Run Code Online (Sandbox Code Playgroud)
然后在JavaScript中执行以下操作
// --myshader.txt
void main() {
gl_FragColor = vec4(1,0,0,1);
}
Run Code Online (Sandbox Code Playgroud)
人们将它们放入HTML中的原因是因为它简单,高效且同步.
简单:与JS文件版本不同,您不必用引号和其他标点符号包围每一行.虽然现在es6不再是问题了.每个支持WebGL的浏览器都支持es6模板字符串.
高效:与text和js文件不同,服务器只有一个请求.当然有些人可能会在他们的js文件上运行一个连接器来修复其中的一些.
同步:与文本文件不同,它们的用法是同步的.无需回调或承诺或以其他方式处理下载文件的异步问题.
至于为什么你的例子不起作用我很确定原因是它允许跨源资源访问.该<script>标签被设计的人想出了跨源访问是一个问题,因此他们不可能在不破坏一堆网站关闭跨原点脚本之前.他们可以使其他一切更加严格.
例如,XMLHttpRequest不允许跨源访问,除非您正在联系的服务器给予权限.如果脚本标记允许您访问该内容,则可以使用脚本标记来解决该限制.换句话说,不是创建XMLHttpRequest并读取request.responseText结果,而只是以编程方式创建脚本标记,将其设置src为所需的URL,然后text在完成后读取其字段.为了确保您不能这样做,您不能阅读text具有src属性的脚本标记的字段
| 归档时间: |
|
| 查看次数: |
15709 次 |
| 最近记录: |