Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么着色器必须在webgl程序的html文件中?_Javascript_Three.js_Glsl_Webgl - Fatal编程技术网

Javascript 为什么着色器必须在webgl程序的html文件中?

Javascript 为什么着色器必须在webgl程序的html文件中?,javascript,three.js,glsl,webgl,Javascript,Three.js,Glsl,Webgl,我看到了以下问题,有人问如何从html中删除着色器: 在包含问题答案中建议的着色器的文件中,可以加载详细的解决方法 在我看到的教程中,着色器代码直接嵌入到html中。 javascript代码使用getElementById引用它。但是,由于许多原因,将着色器直接嵌入到html中是很难看的。为什么我不能使用src=属性在外部引用它 <script type="x-shader/x-fragment" id="shader-fs" src="util/fs"></script&

我看到了以下问题,有人问如何从html中删除着色器:

在包含问题答案中建议的着色器的文件中,可以加载详细的解决方法

在我看到的教程中,着色器代码直接嵌入到html中。 javascript代码使用getElementById引用它。但是,由于许多原因,将着色器直接嵌入到html中是很难看的。为什么我不能使用src=属性在外部引用它

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

以上这些都不行,我只是想知道为什么不行。这显然与脚本本身的限制有关,但我不明白。着色器语言脚本只是文本。文本可以从任何地方抓取或生成(您可以读取或生成文本)。许多教程只是跳过了魔术发生的部分,WebGL着色器实例是从获得的字符串创建的。没有理由不能像您建议的那样从外部引用脚本,但是您需要额外的JavaScript来加载内容,而不是浏览器。脚本标记可能会在教程中使用,这主要是因为如果您为脚本标记指定了浏览器无法理解的类型,浏览器将跳过标记内容的执行或脚本源的检索,因此标记的内容和属性可以按您的意愿使用

编辑:嗯,我得把一些东西拿回去。我决定浏览四种浏览器(Chrome、Firefox、IE9、Opera),看看当你有一行代码时会发生什么

<script type="x-shader/x-fragment" id="shader-fs" src="util/fs"></script>
当给定部分路径时,警告文件的完整路径。(这可能是您的问题?当浏览器为您提供完整路径时,您期望的是部分路径?)此外,我不确定如何解释您的问题。

Update 2018 在2018年,我建议使用多行模板文字,就像在着色器周围使用背景标记一样,它可以跨越多行

const someShaderSource = `
attribute vec4 position;
uniform mat4 matrix;
void main() {
  gl_Position = matrix * position;
}
`;
如果您想将着色器放在单独的文件中,您可以在2018年使用JavaScript模块轻松实现这一点。着色器文件可能如下所示

// someshader.glsl.js
export default `
attribute vec4 position;
uniform mat4 matrix;
void main() {
  gl_Position = matrix * position;
}
`;
<script type="module">
import someShaderSource from './someshader.glsl.js';

// use someShadeSource
</script>
要使用JavaScript模块,主JavaScript必须位于单独的文件中。可以通过导入着色器源来访问该着色器源

// main.js

import someShaderSource from './someshader.glsl.js';

// use someShadeSource
您可以使用

<script src="main.js" type="module"></script>
或其他常见格式

// --myshader.js--
var myFragmentShader = [
  "void main() {",
  "  gl_FragColor = vec4(1,0,0,1);", 
  "}",
].join("\n");
在所有支持WebGL的浏览器中,您都可以使用

否则,您可以将它们放在文本文件中,并使用XMLHTTPRequest加载它们

// --myshader.txt
  void main() {
    gl_FragColor = vec4(1,0,0,1); 
  }
然后在JavaScript中执行以下操作

function loadTextFile(url, callback) {
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.addEventListener('load', function() {
     callback(request.responseText);
  });
  request.send();
}

loadTextFile("myshader.txt", function(text) {
  // use text...
});
人们之所以将它们放在HTML中,是因为它简单、高效且同步

简单:与JS文件版本不同,您不必用引号和其他标点符号围绕每一行。尽管现在使用es6,这不再是一个问题。每个支持WebGL的浏览器都支持es6模板字符串

高效:与文本和js文件不同,只有一个对服务器的请求。当然,有些人可能会在他们的js文件上运行连接器来修复其中的一些问题

同步:与文本文件不同,它们的使用是同步的。不需要回调或承诺,也不需要处理下载文件的异步问题

至于为什么您的示例不起作用,我很确定原因是它将允许跨源资源访问。
标签是在人们意识到跨源访问是一个问题之前设计的,因此他们无法在不破坏大量站点的情况下关闭跨源脚本。他们可以让其他的事情更加严格


例如,除非您联系的服务器授予权限,否则XMLHttpRequest不允许跨源访问。如果脚本标记允许您访问该内容,您可以使用脚本标记绕过该限制。换句话说,与其进行XMLHttpRequest并读取
请求.responseText
,不如通过编程创建一个脚本标记,将其
src
设置为所需的URL,然后在完成后读取其
文本
字段。为了确保您不能这样做,您不允许读取具有
src
属性的脚本标记的
文本
字段

,您根本不必使用
标记来加载着色器程序。大多数教程和示例只是将它们用作在网页的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);"+     
        "}"
    ;
然后,您将编译着色器,如下所示:

var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, myVertexShaderSrc);
gl.compileShader(vertexShader);

gl.attachShader(program, vertexShader);

这并不能回答问题。我试图重写脚本以从外部提取脚本文本。忘记没有支持的文本类型“x-shader/x-fragment”,这个家伙在他的加载程序代码中使用它。为什么src=“util/fs”不起作用???更新了答案。如果这个答案不起作用,它可能会帮助您在问题中添加如何提取外部源代码的内容。对此进行表决是因为,虽然已经提出了一个解决方案,但了解原始示例不起作用的原因很有用。它被否决(我认为),因为它说明了脚本标记不起作用,但如果我使用ES6格式,我能让Babel transcompile成为字符串版本之一吗?对不起,我忽略了你说的每个支持WebGL的浏览器也支持模板字符串的部分。如果是这种情况,我想知道为什么将GLSL存储为实际字符串似乎更常见?老实说,使用这种格式太糟糕了。@zwcloud:我是用
function loadTextFile(url, callback) {
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.addEventListener('load', function() {
     callback(request.responseText);
  });
  request.send();
}

loadTextFile("myshader.txt", function(text) {
  // use text...
});
// myVertextShader.glsl.js
var myVertexShaderSrc =         
        "attribute vec3 pos;"+      
        "void main() {"+        
        "   gl_Position = vec4(pos, 1.0);"+     
        "}"
    ;
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, myVertexShaderSrc);
gl.compileShader(vertexShader);

gl.attachShader(program, vertexShader);