I modified a minecraft-ish demo so you can jump around and place blocks. But the texture of the blocks I construct is smoothed and not pixelated for some reason.
The source I think is relevant:
var textureDirt = THREE.ImageUtils.loadTexture( 'img/dirt.png' );
textureGrass.magFilter = THREE.NearestFilter;
textureGrass.minFilter = THREE.LinearMipMapLinearFilter;
var material = new THREE.MeshLambertMaterial( { map: textureDirt, ambient: 0xbbbbbb, vertexColors: THREE.VertexColors } );
var geometry = new THREE.CubeGeometry(1,1,1);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.x = point[0];
mesh.position.y = point[1];
mesh.position.z = point[2];
// for physics
mesh.blockType = type;
world[point] = mesh;
scene.add(mesh);
Live demo:
http://ubershmekel.github.com/mine3js/
The rest of the source:
https://github.com/ubershmekel/mine3js/blob/master/js/main.js
After reviewing the question, I found the bug. I didn't apply the filters to the dirt material
textureGrass.magFilter = THREE.NearestFilter;
textureGrass.minFilter = THREE.LinearMipMapLinearFilter;
Should have been
textureDirt.magFilter = THREE.NearestFilter;
textureDirt.minFilter = THREE.LinearMipMapLinearFilter;
Related
I have a dash streaming video. According to its title, it is a 3*3. Now I can splice the complete video through the THREE,
// 3*3 PlaneGeometry
var geometry = new THREE.PlaneGeometry(400, 200, 3, 3);
const video1 = document.getElementById("videos1");
...................
...................
const texture1 = new THREE.VideoTexture(video3);
texture1.maxFilter = THREE.NearestFilter;
texture1.minFilter = THREE.NearestFilter;
...................
...................
var geometryfaces = geometry.faces;
for (let i = 0; i < geometryfaces.length; i++) {
const faces = geometryfaces[i];
materials[i] = new THREE.MeshBasicMaterial({
map: textures[i],
});
}
var uv = [
new THREE.Vector2(0, 0),
new THREE.Vector2(0, 1),
new THREE.Vector2(1, 1),
new THREE.Vector2(1, 0),
];
// Set the texture coordinates
for (var m = 0; m < geometryfaces.length; m += 2) {
geometry.faces[m].materialIndex = faceId;
console.log(geometry.faces);
geometry.faces[m + 1].materialIndex = faceId;
geometry.faceVertexUvs[0][m] = [uv[2], uv[3], uv[1]];
geometry.faceVertexUvs[0][m + 1] = [uv[3], uv[0], uv[1]];
faceId++;
}
var bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry);
var material = new THREE.MeshFaceMaterial(materials);
var mesh = new THREE.Mesh(bufferGeometry, material); //网格模型对象Mesh
This way I can get a full flat video, but this video is panoramic and I need to render it on the ball, and I don't know much about the UV of the ball。
I need help. Thank you
picture:enter image description here
picture2:enter image description here
Three.js SphereGeometry automatically creates the UV mapping for you. Since the image you're using is equirectangular, you can just map the image onto the inside of the sphere for the effect you want:
var camera, scene, renderer, vp, sphere;
vp = new THREE.Vector2(window.innerWidth, window.innerHeight);
// Init WebGL stuff
function init() {
// WebGL Renderer
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(vp.x, vp.y);
renderer.domElement.classList.add("canvasWebGL");
// append to DOM
document.body.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0xe1e1e1);
// camera
camera = new THREE.PerspectiveCamera(55, vp.x / vp.y, 0.05, 100);
// Sphere radius is large enough to surround the camera
let sphereGeom = new THREE.SphereGeometry( 20, 128, 128 );
// Just use your equirect image as the texture
// And render the INSIDE of the sphere, not the outside
const tex = new THREE.TextureLoader().load("https://i.imgur.com/1VECsLy.jpg");
let sphereMat = new THREE.MeshBasicMaterial({
map: tex,
side: THREE.BackSide
});
sphere = new THREE.Mesh(sphereGeom, sphereMat);
scene.add(sphere);
}
function animate(s) {
sphere.rotation.set(
Math.cos(s / 3000), s / 3000, 0
);
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
init();
animate(0);
<script src="https://cdn.jsdelivr.net/npm/three#0.123/build/three.js"></script>
Read more about sphere geometry here: https://threejs.org/docs/?q=material#api/en/geometries/SphereGeometry
I want to show a simple plane and a simple cube but the plane hides the cube, the cube is located between the camera and the plane, but the plane "hides" the cube.
This is my scene without plane:
and here it is with the plane added:
I am pretty sure they are in a location where the cube should to be showed.
Here is my code:
var scene = new THREE.Scene(),
camera = new THREE.PerspectiveCamera(45,Window.innerWidth,window.innerHeight,0.1,1000),
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
var axes = new THREE.AxisHelper(20);
scene.add(axes);
var cubeGeometry = new THREE.CubeGeometry(4,4,4);
var cubeMaterial = new THREE.MeshBasicMaterial({color:0x777777});
var cube = new THREE.Mesh(cubeGeometry,cubeMaterial);
//cube.castShadow = true;
cube.position.x = 0;
cube.position.y = 10;
cube.position.z = 5;
scene.add(cube);
var planeGeometry = new THREE.PlaneGeometry(60,20);
var planeMaterial = new THREE.MeshBasicMaterial({color: 0x55cc88});
var plane = new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x = -0.5*Math.PI;
plane.position.x = 15;
plane.position.y = 0;
plane.position.z = 0;
//scene.add(plane);
//plane.receiveShadow = true;
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40,60,-10);
scene.add(spotLight);
//renderer.setClearColor(0xEEEEEE,1);
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.render(scene,camera);
$("#WebGl-salida").append(renderer.domElement);
Pay attention to names of objects and order and correctness of parameters in methods:
camera = new THREE.PerspectiveCamera(45,Window.innerWidth,window.innerHeight,0.1,1000)
should be like:
camera = new THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000)
jsfiddle example
Many thanks! Both for the answer and for the suggestion to edit the question to make it more understandable (my English has to improve) Now it is working perfectly.
Using r70, the shadow shows as expected - r70 example (Shadow it correct shape)
Using r76 however, the shadow is abnormally shaped - r76 example (Shadow is abnormally shaped)
You can see that the shadows on the MeshLambertMaterial on the ground plane are not as expected.
Why is the shadows becoming abnormally shaped?
What needs to be changed to get it working in r76?
Here is the code I am using (same in both example):
var light;
light = new THREE.SpotLight(0xdfebff, 1);
light.position.set(300, 400, 50);
light.castShadow = true;
light.shadowCameraVisible = true;
scene.add(light);
var groundMaterial = new THREE.MeshLambertMaterial({
color: 0xFF0000,
});
plane = new THREE.Mesh(new THREE.PlaneGeometry(500, 500), groundMaterial);
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
plane.castShadow = false;
scene.add(plane);
var boxgeometry = new THREE.CubeGeometry(100, 100, 100);
var boxmaterial = new THREE.MeshLambertMaterial({
color: 0x0aeedf
});
var cube = new THREE.Mesh(boxgeometry, boxmaterial);
cube.castShadow = true;
cube.position.x = 0;
cube.position.y = 100;
cube.position.z = 0;
scene.add(cube);
webglRenderer = new THREE.WebGLRenderer({ alpha: true });
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
webglRenderer.shadowMapEnabled = true;
webglRenderer.shadowMapSoft = true;
The first thing to do is to add a shadow camera helper so you can see what is going on:
light.shadowCameraHelper = new THREE.CameraHelper( light.shadow.camera );
scene.add( light.shadowCameraHelper );
It is clear that the shadow camera frustum is clipping the shadow.
Starting in three.js r.76, the shadow camera frustum is automatically set so it more closely matches the spotLight field-of-view.
If you would like to override that, you can specify a custom shadow frustum like so:
// custom shadow frustum
light.shadow = new THREE.LightShadow( new THREE.PerspectiveCamera( 30, 1, 200, 700 ) );
updated fiddle: http://jsfiddle.net/ef4r5s76/5/
three.js r.76/r.77
My code :
Directional light :
light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(-50, 50, 300);
light.castShadow = true;
light.shadowDarkness = 0.4;
light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;
scene.add(light);
Sprite :
var spriteMaterial = new THREE.SpriteMaterial({map: texture});
var info = new THREE.Sprite( spriteMaterial );
info.castShadow = true;
info.scale.set(infoScale, infoScale, infoScale);
info.name = continent.label;
info.userData.continent = continent;
info.userData.id = continent.id;
info.userData.type = 'info';
hubInfos.push(info);
Here is the result my aircraft has a shadow but not the sprite
Sprites in three.js do not cast shadows.
One work-around is to use PlaneGeometry like so:
scene.add( plane );
plane.lookAt( camera );
Note: LookAt() will not work correctly if the plane is a child of a rotating object; it must be a child of the scene.
three.js r.74
PRoblem: i'm trying to create (just for fun) a simple poker card (with a card back and a card front).
I have two different images, for back and front.
I easily created a Plane geometry with a single texture for both sides, but i really don't know how to assign a texture for a side and the other texture for the other side...
i tried this (without success :( ):
var textureBack = new THREE.ImageUtils.loadTexture( 'images/cardBack.png' );
var textureFront = new THREE.ImageUtils.loadTexture( 'images/cardFront.png' );
var material1 = new THREE.MeshBasicMaterial( { map: textureBack } );
var material2 = new THREE.MeshBasicMaterial( { map: textureFront } );
var geometry = new THREE.PlaneGeometry( 90, 110, 1, 1 );
geometry.faces[ 0 ].materials.push( material1 );
geometry.faces[ 1 ].materials.push( material2 );
var card = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial());
any help, please? :)
Was searching for solution without duplicating all my geometry.
Here you go ladies and gentlemen...
var materials = [new THREE.MeshBasicMaterial({map: texture, side: THREE.FrontSide}),
new THREE.MeshBasicMaterial({map: textureBack, side: THREE.BackSide})];
var geometry = new THREE.PlaneGeometry(width, height);
for (var i = 0, len = geometry.faces.length; i < len; i++) {
var face = geometry.faces[i].clone();
face.materialIndex = 1;
geometry.faces.push(face);
geometry.faceVertexUvs[0].push(geometry.faceVertexUvs[0][i].slice(0));
}
scene.add(new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials)));
BOOM a Two Faced Plane for ya, the loop will also work with geometries with more faces, replicating each face and applying the BackSide texture to it.
Enjoy!
You need to place two plane geometries back-to-back.
First, create a geometry for the front.
var geometry1 = new THREE.PlaneGeometry( 90, 110, 1, 1 );
Now create another geometry for the back.
var geometry2 = new THREE.PlaneGeometry( 90, 110, 1, 1 );
Spin it 180 degrees.
geometry2.applyMatrix( new THREE.Matrix4().makeRotationY( Math.PI ) );
After you load the materials, create the meshes, and add them as children of a "card" object.
// textures
var textureFront = new THREE.ImageUtils.loadTexture('images/cardFront.png' );
var textureBack = new THREE.ImageUtils.loadTexture('images/cardBack.png' );
// material
var material1 = new THREE.MeshBasicMaterial( { color: 0xffffff, map: textureFront } );
var material2 = new THREE.MeshBasicMaterial( { color: 0xffffff, map: textureBack } );
// card
card = new THREE.Object3D();
scene.add( card );
// mesh
mesh1 = new THREE.Mesh( geometry1, material1 );
card.add( mesh1 );
mesh2 = new THREE.Mesh( geometry2, material2 );
card.add( mesh2 );
You'll have an easier time with this if you use WebGLRenderer.
Fiddle: http://jsfiddle.net/mdAb7/11/
Updated to three.js r.69