Reputation: 273
This has been asked before (2 years ago) and in several places both in ThreeJS github and SO. But still many (including me) are having problems with this. This is what I got now (which is part of a larger system):
function dataLoader()
{
this.data_count = 0;
this.data_array = new Array();
}
function loadFile( file, loader ){
var FileObject = new Object();
FileObject.data = "";
FileObject.ready = false;
FileObject.id = loader.data_count;
loader.data_array[loader.data_count] = false;
$.ajax({
type: "GET",
url: file,
dataType: "text"
}).done( function( msg ) {
FileObject.data = msg;
FileObject.ready = true;
loader.data_array[FileObject.id] = true;
});
loader.data_count += 1;
return FileObject;
}
And then I do this:
var loader = new dataLoader();
var SkyVertexShader = loadFile( "Shaders/sky.frag", loader );
var SkyFragmentShader = loadFile( "Shaders/sky.vertex", loader );
And then I create material like this:
var skyMat = new THREE.ShaderMaterial( { vertexShader: SkyVertexShader.data, fragmentShader: SkyFragmentShader.data, uniforms: uniforms, side: THREE.BackSide } );
Shaders in sky.frag and sky.vertex are plain text without any tags or anything. When I debug I can see that SkyFragmentShader.data and SkyVertexShader.data are both correctly set. Shaders are the ones from webgl_lights_hemisphere example. But when I load I get this error:
ERROR: 0:37: 'modelMatrix' : undeclared identifier
ERROR: 0:37: 'position' : undeclared identifier
ERROR: 0:37: 'constructor' : not enough data provided for construction
ERROR: 0:38: 'assign' : l-value required "vWorldPosition" (can't modify a varying) ERROR: 0:40: 'gl_Position' : undeclared identifier
ERROR: 0:40: 'projectionMatrix' : undeclared identifier
ERROR: 0:40: 'modelViewMatrix' : undeclared identifier
ERROR: 0:40: 'constructor' : not enough data provided for construction
ERROR: 0:40: 'assign' : cannot convert from '4-component vector of float' to 'float' �
But it works when I just do this (so like in the examples):
var fragmentShader = document.getElementById( 'fragmentShader' ).textContent;
var vertexShader = document.getElementById( 'vertexShader' ).textContent;
var skyMat = new THREE.ShaderMaterial( { vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide } );
This last part of course works only when having the shaders in HTML. So even though the content is virtually identical between the .textContent method and the Ajax GET method (just some tabs and newlines) it shows syntax errors about undefined variables. So what could cause this?
Upvotes: 3
Views: 3953
Reputation: 1463
This is a nice lightweight external shader loader: https://github.com/codecruzer/webgl-shader-loader-js
Upvotes: 2
Reputation: 273
Ok I figured it out. I was loading them in reverse order which made vertex shader the first one and fragment the second one. That made the ThreeJS added code in the wrong position and that trew errors. It sadly made me debug for so long because the errors seemed generic, but its possible to get the full generated shader text via Firebug which helped a lot. But thanks gaitat, it did make me look closer at loading.
Upvotes: 2
Reputation: 12632
If you are referring to this post https://github.com/mrdoob/three.js/issues/283 (which is two years old) you are not exactly following their solution. Have you tried setting "async: false," to your ajax request in order to have a synchronous request because you might be trying to execute the shaders before they have actually loaded.
Upvotes: 0