我想知道如何将实际包含在我的html中的着色器移动到外部文件中。通过这种方式,我将能够将它们包含在我的gulp任务中。我看了一下JavaScript着色器文件是如何编写的,但我不太了解。
例如,使用下面的Glow着色器代码,我该如何将其移动到外部文件?
<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>
答案 0 :(得分:1)
提供的另一个答案是简单地使用GLSL代码并将每一行转换为字符串。每个字符串都是数组中的值。 join
调用将所有字符串与\n
字符连接起来,以便在调试时更容易读取代码。我之前已多次这样做过,并且是您尝试做的事情的合法解决方案。
但是,如果您希望外部文件包含原始GLSL代码,那么您也可以这样做。考虑两个文件:
这些文件包含您通常在脚本标记中使用的着色器代码。您可以使用XMLHTTPRequest来获取文件,并使用返回的文本作为着色器代码。
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文件。
只要我们谈论现代网络......
您还可以选择import
着色器代码。 非常大但它目前仅支持Chrome和Opera(尽管polyfill确实存在)。 Microsoft Edge将功能列为&#34;正在考虑中,&#34;并且Firefox不会缩进以在当前状态下实现它。因此,如果使用大量的盐,请注意:http://caniuse.com/#search=import
在您的HTML中,以及使用它的JavaScript之前......
<link id="vertexImport" rel="import" href="/server/glow_vertex.glsl" />
<link id="fragmentImport" rel="import" href="/server/glow_fragment.glsl" />
稍后在您的JavaScript中:
var material = new THREE.ShaderMaterial({
vertexShader: document.getElementById("vertexImport").import.body.childNodes[0].data,
fragmentShader: document.getElementById("fragmentImport").import.body.childNodes[0].data,
});
同样,这是异步的。您可能需要为每个链接添加onload
处理程序,这样您才能在加载代码之前尝试访问该代码。
答案 1 :(得分:0)
您可以将着色器代码移动到单独的JS文件中,并在three.js之后包含该文件 以下是https://github.com/timoxley/threejs/blob/master/examples/js/shaders/ColorifyShader.js
中的一个示例/**
* @author alteredq / http://alteredqualia.com/
*
* Colorify shader
*/
THREE.ColorifyShader = {
uniforms: {
"tDiffuse": { type: "t", value: null },
"color": { type: "c", value: new THREE.Color( 0xffffff ) }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform vec3 color;",
"uniform sampler2D tDiffuse;",
"varying vec2 vUv;",
"void main() {",
"vec4 texel = texture2D( tDiffuse, vUv );",
"vec3 luma = vec3( 0.299, 0.587, 0.114 );",
"float v = dot( texel.xyz, luma );",
"gl_FragColor = vec4( v * color, texel.w );",
"}"
].join("\n")
};
通过上述内容,您可以创建我们的材料:
material = new THREE.ShaderMaterial({
uniforms : THREE.ColorifyShader.uniforms,
vertexShader : THREE.ColorifyShader.vertexShader,
fragmentShader : THREE.ColorifyShader.fragmentShader
});
当然,您不需要调用对象THREE.ColorifyShader
,您可以随意调用它。
答案 2 :(得分:0)
建议加入一系列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() {...}'
...