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
Opengl es 如何在外部文件中移动着色器脚本?_Opengl Es_Three.js_Shader - Fatal编程技术网

Opengl es 如何在外部文件中移动着色器脚本?

Opengl es 如何在外部文件中移动着色器脚本?,opengl-es,three.js,shader,Opengl Es,Three.js,Shader,我想知道如何将html中实际包含的着色器移动到外部文件中。这样,我就可以将它们包含在我的吞咽任务中。我了解了JavaScript着色器文件是如何编写的,但我不太了解 例如,使用下面的光晕着色器代码,如何将其移动到外部文件 <script type="x-shader/x-vertex" id="vertexShaderGlow"> uniform vec3 viewVector; uniform float c; uniform float p; va

我想知道如何将html中实际包含的着色器移动到外部文件中。这样,我就可以将它们包含在我的吞咽任务中。我了解了JavaScript着色器文件是如何编写的,但我不太了解

例如,使用下面的光晕着色器代码,如何将其移动到外部文件

<script type="x-shader/x-vertex" id="vertexShaderGlow">
    uniform vec3 viewVector;
    uniform float c;
    uniform float p;
    varying float intensity;
    void main()
    {
        vec3 vNormal = normalize( normalMatrix * normal );
        vec3 vNormel = normalize( normalMatrix * viewVector );
        intensity = pow( c - dot(vNormal, vNormel), p );
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }
</script>
<script type="x-shader/x-vertex" id="fragmentShaderGlow">
    uniform vec3 glowColor;
    varying float intensity;
    void main()
    {
        vec3 glow = glowColor * intensity;
        gl_FragColor = vec4( glow, 1.0 );
    }
</script>

均匀vec3视向量;
均匀浮点数c;
均匀浮动p;
浮动强度变化;
void main()
{
vec3 vNormal=规格化(normalMatrix*normal);
vec3 vNormel=规格化(normalMatrix*viewVector);
强度=功率(c-点(vNormal,vNormal),p);
gl_位置=projectionMatrix*modelViewMatrix*vec4(位置,1.0);
}
颜色均匀;
浮动强度变化;
void main()
{
vec3发光=发光颜色*强度;
gl_FragColor=vec4(辉光,1.0);
}

您可以将着色器代码移动到单独的JS文件中,并在三个.JS之后包含该文件。
这里有一个例子

根据以上内容,您可以创建如下材料:

material = new THREE.ShaderMaterial({
  uniforms : THREE.ColorifyShader.uniforms,
  vertexShader : THREE.ColorifyShader.vertexShader,
  fragmentShader : THREE.ColorifyShader.fragmentShader
});

当然,您不需要调用对象
THREE.ColorifyShader
,您可以随意调用它。

您可以将着色器代码移动到单独的JS文件中,并在THREE.JS之后包含该文件。
这里有一个例子

根据以上内容,您可以创建如下材料:

material = new THREE.ShaderMaterial({
  uniforms : THREE.ColorifyShader.uniforms,
  vertexShader : THREE.ColorifyShader.vertexShader,
  fragmentShader : THREE.ColorifyShader.fragmentShader
});

当然,您不需要调用对象
THREE.ColorifyShader
,您可以随意调用它。

提供的另一个答案是简单地使用GLSL代码并将每一行转换为字符串。每个字符串都是数组中的一个值。
join
调用将所有字符串与
\n
字符连接起来,以使调试时代码更易于阅读。我以前曾多次这样做过,这是一个合理的解决方案,可以解决您试图做的事情

但如果您希望使用原始GLSL代码创建外部文件,也可以这样做。考虑这两个文件:

  • glow_vertex.glsl
  • glow_fragment.glsl
这些文件包含脚本标记中通常包含的着色器代码。可以使用获取文件,并将返回的文本用作着色器代码

var vertexShader = null;
var fragmentShader = null;

function shadersDone(){
    var material = new THREE.ShaderMaterial({
        uniforms: { /* define your uniforms */},
        vertexShader: vertexShader,
        fragmentShader: fragmentShader
    });
}

function vertexDone(code){
    vertexShader = code;
    if(fragmentShader !== null){
        shadersDone();
    }
}

function fragmentDone(code){
    fragmentShader = code;
    if(vertexShader !== null){
        shadersDone();
    }
}

var xhr1 = new XMLHttpRequest();
var xhr2 = new XMLHttpRequest();

xhr1.open("GET", "/server/glow_vertex.glsl", true);
xhr2.open("GET", "/server/glow_fragment.glsl", true);

xhr1.responseType = "text";
xhr2.responseType = "text";

xhr1.onload = function(){
    if(xhr1.readyState === xhr1.DONE && xhr1.status === 200){
        vertexDone(xhr1.resultText);
    }
};
xhr2.onload = function(){
    if(xhr2.readyState === xhr2.DONE && xhr2.status === 200){
        fragmentDone(xhr2.resultText);
    }
};

xhr1.send(null);
xhr2.send(null);
注意,这都是异步的。此外,您的服务器需要配置为以纯文本形式发送GLSL文件

只要我们谈论的是现代网络……

还可以选择导入着色器代码非常大,但目前仅在Chrome和Opera中受支持(尽管PolyFill确实存在)。Microsoft Edge将该功能列为“正在考虑中”,Firefox不会缩进以在其当前状态下实现该功能。因此,用一大粒盐来吃下面的东西,并注意:

在HTML中,在使用它的JavaScript之前

<link id="vertexImport" rel="import" href="/server/glow_vertex.glsl" />
<link id="fragmentImport" rel="import" href="/server/glow_fragment.glsl" />

同样,这是异步的。您可能需要为每个链接添加一个
onload
处理程序,以便在加载代码之前不尝试访问代码。

提供的另一个答案是简单地获取GLSL代码并将每一行转换为字符串。每个字符串都是数组中的一个值。
join
调用将所有字符串与
\n
字符连接起来,以使调试时代码更易于阅读。我以前曾多次这样做过,这是一个合理的解决方案,可以解决您试图做的事情

但如果您希望使用原始GLSL代码创建外部文件,也可以这样做。考虑这两个文件:

  • glow_vertex.glsl
  • glow_fragment.glsl
这些文件包含脚本标记中通常包含的着色器代码。可以使用获取文件,并将返回的文本用作着色器代码

var vertexShader = null;
var fragmentShader = null;

function shadersDone(){
    var material = new THREE.ShaderMaterial({
        uniforms: { /* define your uniforms */},
        vertexShader: vertexShader,
        fragmentShader: fragmentShader
    });
}

function vertexDone(code){
    vertexShader = code;
    if(fragmentShader !== null){
        shadersDone();
    }
}

function fragmentDone(code){
    fragmentShader = code;
    if(vertexShader !== null){
        shadersDone();
    }
}

var xhr1 = new XMLHttpRequest();
var xhr2 = new XMLHttpRequest();

xhr1.open("GET", "/server/glow_vertex.glsl", true);
xhr2.open("GET", "/server/glow_fragment.glsl", true);

xhr1.responseType = "text";
xhr2.responseType = "text";

xhr1.onload = function(){
    if(xhr1.readyState === xhr1.DONE && xhr1.status === 200){
        vertexDone(xhr1.resultText);
    }
};
xhr2.onload = function(){
    if(xhr2.readyState === xhr2.DONE && xhr2.status === 200){
        fragmentDone(xhr2.resultText);
    }
};

xhr1.send(null);
xhr2.send(null);
注意,这都是异步的。此外,您的服务器需要配置为以纯文本形式发送GLSL文件

只要我们谈论的是现代网络……

还可以选择导入着色器代码非常大,但目前仅在Chrome和Opera中受支持(尽管PolyFill确实存在)。Microsoft Edge将该功能列为“正在考虑中”,Firefox不会缩进以在其当前状态下实现该功能。因此,用一大粒盐来吃下面的东西,并注意:

在HTML中,在使用它的JavaScript之前

<link id="vertexImport" rel="import" href="/server/glow_vertex.glsl" />
<link id="fragmentImport" rel="import" href="/server/glow_fragment.glsl" />

同样,这是异步的。您可能需要为每个链接添加一个
onload
处理程序,这样您就不会在加载代码之前尝试访问代码。

建议加入一个glsl行数组的答案是一种三行可能会遇到的模式,但在本用例中可能应该避免

它在某种模块中可能很有用,在这种模块中,它是某种着色器的“编译”快照,不打算修改

否则,这种方法的主要缺点是缺少语法突出显示和冗长

现在大多数js代码都是以这种或那种方式转换的。着色器代码应该像这样内联

const myShader = new THREE.ShaderMaterial({
  vertexShader: require('./myVert.vs'),
  fragmentShader: require('./myFrag.vs'),
})
编辑

myVert.vs:

//this is all nicely highlighted in sublime text for example
void main (){ 
    gl_Position = vec4( position.xy, 0., 1.); 
}
myVert.fs:

void main (){ 
    gl_FragColor = vec4(1.,0.,0.,1.); 
}
myClass.js:

class myMaterial extends THREE.ShaderMaterial{
  constructor(){
    super({
      vertexShader: require('./myVert.vs'), 
      //^ becomes vertexShader: 'void main() {...}'
      ...

建议连接一组glsl线的答案是三条线可以遇到的模式,但在本用例中可能应该避免

它在某种模块中可能很有用,在这种模块中,它是某种着色器的“编译”快照,不打算修改

否则,这种方法的主要缺点是缺少语法突出显示和冗长

现在大多数js代码都是以这种或那种方式转换的。着色器代码应该像这样内联

const myShader = new THREE.ShaderMaterial({
  vertexShader: require('./myVert.vs'),
  fragmentShader: require('./myFrag.vs'),
})
编辑

myVert.vs:

//this is all nicely highlighted in sublime text for example
void main (){ 
    gl_Position = vec4( position.xy, 0., 1.); 
}
myVert.fs:

void main (){ 
    gl_FragColor = vec4(1.,0.,0.,1.); 
}
myClass.js:

class myMaterial extends THREE.ShaderMaterial{
  constructor(){
    super({
      vertexShader: require('./myVert.vs'), 
      //^ becomes vertexShader: 'void main() {...}'
      ...

您只需要将着色器代码作为字符串,因此可以使用任何允许您从外部文件引入字符串的方法