I could not load texture to my shader material, only what I see are just black dot. This is my shader.js
THREE.ShaderLib['cloud'] = {
uniforms: {
texture: { type: "t", value: THREE.ImageUtils.loadTexture("img/cloud.png") }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_PointSize = 8.0;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
"}",
].join("\n"),
fragmentShader: [
"varying vec2 vUv;",
"uniform sampler2D texture;",
"void main() {",
"gl_FragColor = texture2D(texture, vUv);",
"}",
].join("\n")
};
and this is how I'm trying to load and use it:
var cloudShader = THREE.ShaderLib["cloud"];
var uniforms = THREE.UniformsUtils.clone(cloudShader.uniforms);
var texture = THREE.ImageUtils.loadTexture("img/cloud.png", undefined, function () {
uniforms.texture.value = texture;
texture.needsUpdate = true;
var _material = new THREE.ShaderMaterial({
fragmentShader: cloudShader.fragmentShader,
vertexShader: cloudShader.vertexShader,
uniforms: uniforms
});
_material.uniforms.texture.value.needsUpdate = true;
var _geometry = new THREE.Geometry();
_geometry.vertices.push(new THREE.Vector3(0, 0, 0));
var _mesh = new THREE.Points(_geometry, _material);
scene.add(_mesh);
});
As You can see I'm trying to set update texture value two times, before and after material is created. It's really simpy example but I have no idea why it is not working in the way that I'm using it. There is no errors in debug console.
I'm using THREE.Points class, because I'm using it to generate clouds as a particle groups.
Thanks in advance for any help.
I could not load texture to my shader material, only what I see are just black dot. This is my shader.js
THREE.ShaderLib['cloud'] = {
uniforms: {
texture: { type: "t", value: THREE.ImageUtils.loadTexture("img/cloud.png") }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_PointSize = 8.0;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
"}",
].join("\n"),
fragmentShader: [
"varying vec2 vUv;",
"uniform sampler2D texture;",
"void main() {",
"gl_FragColor = texture2D(texture, vUv);",
"}",
].join("\n")
};
and this is how I'm trying to load and use it:
var cloudShader = THREE.ShaderLib["cloud"];
var uniforms = THREE.UniformsUtils.clone(cloudShader.uniforms);
var texture = THREE.ImageUtils.loadTexture("img/cloud.png", undefined, function () {
uniforms.texture.value = texture;
texture.needsUpdate = true;
var _material = new THREE.ShaderMaterial({
fragmentShader: cloudShader.fragmentShader,
vertexShader: cloudShader.vertexShader,
uniforms: uniforms
});
_material.uniforms.texture.value.needsUpdate = true;
var _geometry = new THREE.Geometry();
_geometry.vertices.push(new THREE.Vector3(0, 0, 0));
var _mesh = new THREE.Points(_geometry, _material);
scene.add(_mesh);
});
As You can see I'm trying to set update texture value two times, before and after material is created. It's really simpy example but I have no idea why it is not working in the way that I'm using it. There is no errors in debug console.
I'm using THREE.Points class, because I'm using it to generate clouds as a particle groups.
Thanks in advance for any help.
Share Improve this question asked Oct 21, 2015 at 7:54 blindeplblindepl 2874 silver badges14 bronze badges 4- Are you sure you are able to access local file on your browser? – Ale_32 Commented Oct 21, 2015 at 9:00
- what local file ? You mean cloud.png ?, yes I'm sure :) – blindepl Commented Oct 21, 2015 at 9:37
- Why are you calling loadTexture twice? – 2pha Commented Oct 22, 2015 at 11:06
- just to test, I've already try to load in only one place, nothing change – blindepl Commented Oct 22, 2015 at 12:20
3 Answers
Reset to default 4So, after some time I have found a solution for this specific problem. I need to move my uniforms from shader.js directly to place where i'm creating shader material. This is enough to fix problem with my texture, but still I don't know why previous code doesn't work. Working shader material looks like this:
var _material = new THREE.ShaderMaterial({
fragmentShader: cloudShader.fragmentShader,
vertexShader: cloudShader.vertexShader,
uniforms: uniforms: {
texture: { type: "t", value: THREE.ImageUtils.loadTexture("img/cloud.png") }
},
});
So if anyone having the same issue now. The reason this doesn't work is not only because of the texture being a reserved keyword in GLSL 4.
When using particles in ThreeJS, and particurarly THREE.Points class, you should always pass gl_PointCoord to the texture2D as a second argument instead of the uv coordinates.
The working example would be:
THREE.ShaderLib['cloud'] = {
uniforms: {
uTexture: { type: "t", value: THREE.ImageUtils.loadTexture("img/cloud.png") }
},
vertexShader: [
"void main() {",
"gl_PointSize = 8.0;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
"}",
].join("\n"),
fragmentShader: [
"uniform sampler2D uTexture;",
"void main() {",
"gl_FragColor = texture2D(uTexture, gl_PointCoord);",
"}",
].join("\n")
};
"varying vec2 vUv;",
"uniform sampler2D texture;",
"void main() {",
"gl_FragColor = texture2D(texture, vUv);", // this line
"}",
As of 2024, this line right there causes an error, because the name texture is reserved by another function in the fragment in threejs's shader material.