Rotating a texture using PointCloudMaterial - three.js

When I used CanvasRenderer and SpriteMaterial, I was able to set a texture's rotation using the rotation attribute in the material. So, say for instance the texture is a cone, and I want to rotate it by 180 degrees:
material = new THREE.SpriteMaterial({
map : texture,
transparent : true,
rotation : Math.PI
});
But that doesn't seem to work with PointCloudMaterial in the WebGLRenderer. For example:
material = new THREE.PointCloudMaterial({
depthWrite : true,
alphaTest : 0.1,
map : texture,
transparent : true,
vertexColors : THREE.VertexColors,
rotation : Math.PI
});
So how can I go about rotating a texture with PointCloudMaterial and a PointCloud mesh? Note that in both instances, the texture is loaded as a base64 string, as follows:
var image = document.createElement('img');
var texture = new THREE.Texture(image);
image.src = /* The base64 string */
Thanks so much!

I ended up using the canvas to do this, following the pattern described at Three.js Rotate Texture. This pretty much worked like a charm.

Related

three.js emissive material maps

I'm currently experimenting a bit in three.js, and I'd like to use an emissive map. I've tried just loading a texture into the emissive property of a phong material, but it doesn't work like that, unfortunately. Here's my code:
var params = {
emissive: THREE.ImageUtils.loadTexture( emissive ),
shininess: shininess,
map: THREE.ImageUtils.loadTexture( map ),
normalMap: THREE.ImageUtils.loadTexture( normalMap ),
normalScale: new THREE.Vector2(0,-1),
envMap: this.reflectionCube,
combine: THREE.MixOperation,
reflectivity: 0.05
};
var material = new THREE.MeshPhongMaterial(params);
Can anyone point me in the right direction to get the emissive map working?
You can make a material with emissive (glow) map support by extending the shaders from existing three.js materials (MeshPhong, MeshLambert, etc).
The benefit is you retain all the functionality from the standard three.js material and also add glow map support.
For the purposes of this example, I'll use the three.js Phong shader as a starting point:
Make a "PhongGlowShader" by extending (via UniformsLib/ShaderChunk) the existing Phong shader
Add glow map uniforms:
"glowMap" : { type: "t", value: null },
"glowIntensity": { type: "f", value: 1 },
Add a glow map factor to its fragment shader:
float glow = texture2D(glowMap, vUv).x * glowIntensity * 2.0; // optional * 2.0 and clamp
gl_FragColor.xyz = texelColor.xyz * clamp(emissive + totalDiffuse + ambientLightColor * ambient + glow, 0.0, 2.0) + totalSpecular;
Create a new THREE.ShaderMaterial using that shader, and pass the glow texture along with its usual uniforms
For further details, take a look at this fiddle: http://jsfiddle.net/Qr7Bb/2/.
You'll notice I made a "MeshPhongGlowMaterial" class that inherits from THREE.ShaderMaterial. That's purely optional; you can also just have a function that creates a new THREE.ShaderMaterial with the above shaders and uniforms.
The standard "emissive" property affects the entire surface of the mesh, it has nothing to do with the glow map (instead use the custom "glowIntensity" property for that).

Texturing down plane (WebGL, Three.JS)

I am using three.js. with webGL. I have a single texture file called support.jpg 100x100.
I am creating planes on the fly, with different heights and widths. I need the support.jpg texture to scale to the width and then repeat down the plane. (as soon in image below)
For Example. If the plane was (height:10, width: 10) it would the texture once fiting. If the plane was (height:100, width: 10) it would have 10 of the textures repeating 10by10. If the plane was (height:100, width: 50) it would have 2 of the textures repeating 50by50.
Question: How Do I Create a plane that will have the correct texture mapping.
Here is what I have so far, but it is only rendering a single texture. (this is a width 200, height 800)
function CreateSupportBeam() {
var mesh, texture, material;
texture = THREE.ImageUtils.loadTexture("images/support.png");
material = new THREE.MeshBasicMaterial({ map: texture, transparent: true });
var uvs = [];
uvs.push(new THREE.Vector2(0,0));
uvs.push(new THREE.Vector2(1,0));
uvs.push(new THREE.Vector2(1,4));
uvs.push(new THREE.Vector2(0,4));
var geo = new THREE.PlaneGeometry(200, 800);
geo.faceVertexUvs[0].push([uvs[0], uvs[1], uvs[2], uvs[3]]);
mesh = new THREE.Mesh(geo, material);
scene.add(mesh);
}
rollercoaster.dickinsonbros.com/ <- This is the project I am working on.
You do not need to change the UVs.
Use a pattern like the following to avoid distortion and ensure that the pattern repeats and starts at the "top".
var geometry = new THREE.PlaneGeometry( length, height );
var scale = height / length;
var offset = Math.floor( scale ) - scale;;
var texture = THREE.ImageUtils.loadTexture( ... );
texture.wrapT = THREE.RepeatWrapping;
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.repeat.set( 1, scale );
texture.offset.set( 0, offset );
If that is not exactly what you are looking for, experiment until you get it the way you want it.
three.js r.66

Three.js use framebuffer as texture

I'm using an image in a canvas element as a texture in Three.js, performing image manipulations on the canvas using JavaScript, and then calling needsUpdate() on the texture. This works, but it's quite slow.
I'd like to perform the image calculations in a fragment shader instead. I've found many examples which almost do this:
Shader materials: http://mrdoob.github.io/three.js/examples/webgl_shader2.html This example shows image manipulations performed in a fragment shader, but that shader is functioning as the fragment shader of an entire material. I only want to use the shader on a texture, and then use the texture as a component of a second material.
Render to texture: https://threejsdoc.appspot.com/doc/three.js/examples/webgl_rtt.html This shows rendering the entire scene to a WebGLRenderTarget and using that as the texture in a material. I only want to pre-process an image, not render an entire scene.
Effects composer: http://www.airtightinteractive.com/demos/js/shaders/preview/ This shows applying shaders as a post-process to the entire scene.
Edit: Here's another one:
Render to another scene: http://relicweb.com/webgl/rt.html This example, referenced in Three.js Retrieve data from WebGLRenderTarget (water sim), uses a second scene with its own orthographic camera to render a dynamic texture to a WebGLRenderTarget, which is then used as a texture in the primary scene. I guess this is a special case of the first "render to texture" example listed above, and would probably work for me, but seems over-complicated.
As I understand it, ideally I'd be able to make a new framebuffer object with its own fragment shader, render it on its own, and use its output as a texture uniform for another material's fragment shader. Is this possible?
Edit 2: It looks like I might be asking something similar to this: Shader Materials and GL Framebuffers in THREE.js ...though the question doesn't appear to have been resolved.
Render to texture and Render to another scene as listed above are the same thing, and are the technique you want. To explain:
In vanilla WebGL the way you do this kind of thing is by creating a framebuffer object (FBO) from scratch, binding a texture to it, and rendering it with the shader of your choice. Concepts like "scene" and "camera" aren't involved, and it's kind of a complicated process. Here's an example:
http://learningwebgl.com/blog/?p=1786
But this also happens to be essentially what Three.js does when you use it to render a scene with a camera: the renderer outputs to a framebuffer, which in its basic usage goes straight to the screen. So if you instruct it to render to a new WebGLRenderTarget instead, you can use whatever the camera sees as the input texture of a second material. All the complicated stuff is still happening, but behind the scenes, which is the beauty of Three.js. :)
So: To replicate a WebGL setup of an FBO containing a single rendered texture, as mentioned in the comments, just make a new scene containing an orthographic camera and a single plane with a material using the desired texture, then render to a new WebGLRenderTarget using your custom shader:
// new render-to-texture scene
myScene = new THREE.Scene();
// you may need to modify these parameters
var renderTargetParams = {
minFilter:THREE.LinearFilter,
stencilBuffer:false,
depthBuffer:false
};
myImage = THREE.ImageUtils.loadTexture( 'path/to/texture.png',
new THREE.UVMapping(), function() { myCallbackFunction(); } );
imageWidth = myImage.image.width;
imageHeight = myImage.image.height;
// create buffer
myTexture = new THREE.WebGLRenderTarget( width, height, renderTargetParams );
// custom RTT materials
myUniforms = {
colorMap: { type: "t", value: myImage },
};
myTextureMat = new THREE.ShaderMaterial({
uniforms: myUniforms,
vertexShader: document.getElementById( 'my_custom_vs' ).textContent,
fragmentShader: document.getElementById( 'my_custom_fs' ).textContent
});
// Setup render-to-texture scene
myCamera = new THREE.OrthographicCamera( imageWidth / - 2,
imageWidth / 2,
imageHeight / 2,
imageHeight / - 2, -10000, 10000 );
var myTextureGeo = new THREE.PlaneGeometry( imageWidth, imageHeight );
myTextureMesh = new THREE.Mesh( myTextureGeo, myTextureMat );
myTextureMesh.position.z = -100;
myScene.add( myTextureMesh );
renderer.render( myScene, myCamera, myTexture, true );
Once you've rendered the new scene, myTexture will be available for use as a texture in another material in your main scene. Note that you may want to trigger the first render with the callback function in the loadTexture() call, so that it won't try to render until the source image has loaded.

Mesh with texture background color

I create a Mesh having a PlaneGeometry and the material defined by a texture loaded from a JPEG image. Everything is fine, excepting that there is a small amount of time before the texture image is loaded when the plane is displayed using a dark color. Is there a way to change this color to something else?
I tried the color option for material, but it is not applied.
var texture = new THREE.ImageUtils.loadTexture('/path/to/image');
texture.minFilter = THREE.LinearMipMapLinearFilter;
texture.magFilter = THREE.NearestFilter;
var material = new THREE.MeshBasicMaterial({
side : THREE.DoubleSide,
map : texture,
color : 0xf0f0f0
// this doesn't seem to work
});
var geometry = new THREE.PlaneGeometry(Math.abs(line.x1 - line.x0), depth);
var mesh = new THREE.Mesh(geometry, material);
That black color is the texture rendering without any texture data. The easiest fix is to load the texture and the mesh, but do not render the mesh until both have fully loaded.
Another option is to create a very small 1x1 texture that is the color you want, use that as your texture initially, and then change the mesh material to your final texture once the desired texture has fully loaded.

3d object that looks the same from every direction

have a 3d maze with walls and floor.
have an image with a key ( or other object its not important, but all of em are images and not 3d models ).
I want to display it on the floor and if the camera moves around the object needs to look the same without rotating the object. How can i achieve this?
Update1:
I created a plane geometry added the image ( its a transparent png ) and rotating at render. Its working good, but if i turn the camera sometimes the plane lose transparency for about a few milisec and the get a solid black background ( blinking ).
Any idea why?
here is the code:
var texture = new THREE.ImageUtils.loadTexture('assets/images/sign.png');
var material = new THREE.MeshBasicMaterial( {map: texture, transparent: true} );
plane = new THREE.Mesh(new THREE.PlaneGeometry(115, 115,1,1), material );
plane.position.set(500, 0, 1500);
scene.add(plane);
// at render:
plane.rotation.copy( camera.rotation );
This will be achieved by using:
function animate() {
not3dObject.rotation.z = camera.rotation.z;
not3dObject.rotation.x = camera.rotation.x;
not3dObject.rotation.y = camera.rotation.y;
...
render();
}

Resources