I was trying to render text in three.js using TextGeometry but got an empty black screen. I suspected that was an issue with the camera and I added simple green box, that box was rendered correctly.
// tslint:disable-next-line:no-var-requires
const fontJson = require("./fonts/gentilis_bold.typeface.json");
import "./index.scss";
import * as THREE from "three";
(window as any).THREE = THREE;
import "./controls/OrbitControls";
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
camera.lookAt(scene.position);
const textMaterial = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
console.log(new THREE.Font(fontJson))
const textGeometry = new THREE.TextGeometry("Hello amigo", {
font: new THREE.Font(fontJson),
size: 80,
height: 5,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 8,
});
const textMesh = new THREE.Mesh(textGeometry, textMaterial);
// const geometry = new THREE.BoxGeometry(1, 1, 1);
// const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// const mesh = new THREE.Mesh(geometry, material);
// scene.add(mesh);
scene.add(textMesh);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener("change", () => {
renderer.render(scene, camera);
});
renderer.render(scene, camera);
I have found the problem, sorry for the delay. If you use MeshPhongMaterial texture or others (except MeshBasicMaterial) you should add some lights to your scene. Just add this lines to your scene.
const pointLight = new THREE.PointLight(0xffffff, 1.5); pointLight.position.set(0, 100, 90);
scene.add(pointLight);
pointLight.color.setHSL(Math.random(), 1, 0.5);
const textMaterials = [
new THREE.MeshPhongMaterial({ color: 0xffffff, flatShading: true }),
new THREE.MeshPhongMaterial({ color: 0xffffff }),
];
Related
I want to create a sun surrounded with a large ring or orbit in three.js. Here is my source code (using require.js modules):
require(['js/interactive.js', 'js/OrbitControls.js', 'js/three.min.js'], function (InteractionManager, OrbitControls, THREE) {
const ZOOM = 300;
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(window.innerWidth / -ZOOM, window.innerWidth / ZOOM, window.innerHeight / ZOOM, window.innerHeight / - ZOOM, 1, 1000);
const renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true });
renderer.setSize(window.innerWidth, window.innerHeight);
// renderer.setClearColorHex( 0x555555, 1 );
document.body.appendChild(renderer.domElement);
// new a interaction, then you can add interaction-event with your free style
const interaction = new InteractionManager(renderer, camera, renderer.domElement);
const loader = new THREE.TextureLoader();
const controls = new OrbitControls(camera, renderer.domElement);
const light = new THREE.AmbientLight(0xffffff); // soft white light
scene.add(light);
// const light2 = new THREE.PointLight(0xffffff); // soft white light
// light2.position.set(10, 0, 0);
// scene.add(light2);
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshPhongMaterial({
map: loader.load('./resources/2k_sun.jpeg'),
specular: 0x555555,
shininess: 50
});
const sun = new THREE.Mesh(geometry, material);
scene.add(sun);
interaction.add(sun);
sun.addEventListener('click', function(ev) {
var bb = new THREE.Box3()
bb.setFromObject(sun);
bb.getCenter(controls.target);
camera.zoom = 1;
camera.updateProjectionMatrix();
});
const ringGeometry = new THREE.RingGeometry(50, 51, 32);
const ringMaterial = new THREE.MeshBasicMaterial( { color: 0x808080, side: THREE.DoubleSide } );
const ring = new THREE.Mesh( ringGeometry, ringMaterial );
scene.add( ring );
camera.position.set(0, 0, 5);
controls.update();
const animate = function () {
requestAnimationFrame(animate);
sun.rotation.x += 0.01;
sun.rotation.y += 0.01;
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
};
animate();
})
interactive.js is an interaction library I downloaded from here. I used it to zoom in on the sun when it's clicked.
However, when I run this code, parts of the ring will not render at certain angles. This is only fixed if I make the ring much smaller. Below is a screenshot of this behavior:
My question: How can I make this ring fully visible at any angle and maintain the large size?
I would like to make IcosahedronGeometry in three.js and reflect an image on the front side of the geometry.
I already made a IcosahedronGeometry and made it rotate on it's axis.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// RENDERER
var renderer = new THREE.WebGLRenderer({
antialias: true
});
// RENDERER - SIZE OF CANVAS
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor('#ffffff');
document.body.appendChild(renderer.domElement);
// RESPONSIVE RENDERING
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
var groundMaterial = new THREE.MeshPhongMaterial({
shininess: 100,
color: 0xffffff,
specular: 0xffffff
});
const cubeCamera = new THREE.CubeCamera(75, 1000, 512);
scene.add(cubeCamera);
// GEOMETRY
var geometry = new THREE.IcosahedronGeometry(2, 1);
var material = new THREE.MeshStandardMaterial({
color: 0x98bbbd,
side: THREE.FrontSides,
roughness: 1,
metalness: 0.5,
envMap: cubeCamera.renderTarget
});
material.roughness = 0;
material.metalness = 1;
material.flatShading = true;
material.envMap = cubeCamera.renderTarget.texture;
var sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
console.log(sphere.position);
console.log(cubeCamera.position);
cubeCamera.position.copy(sphere.position);
cubeCamera.update(renderer, scene);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture('images/woman.png');
// floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
// floorTexture.repeat.set(1000, 1000);
var floorMaterial = new THREE.MeshBasicMaterial({
map: floorTexture,
side: THREE.BackSide
});
var floorGeometry = new THREE.PlaneGeometry(5, 5, 1, 1);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = 0;
floor.position.x = 0;
floor.position.z = 3;
scene.add(floor);
cubeCamera.lookAt(floor);
// CONTROLS
var orbit = new THREE.OrbitControls(camera, renderer.Mesh);
camera.position.z = 5;
// LIGHTS
var topLeftLight = new THREE.PointLight(0xffffff, 1, 1);
topLeftLight.position.set(-50, 50, -25);
scene.add(topLeftLight);
var topRightLight = new THREE.PointLight(0xffffff, 1, 10);
topRightLight.position.set(50, 150, -25);
scene.add(topRightLight);
var lightBottomRight = new THREE.PointLight(0xffffff, 1, 100);
lightBottomRight.position.set(40, -50, 25);
scene.add(lightBottomRight);
var lightBottomLeft = new THREE.PointLight(0xffffff, 1, 100);
lightBottomLeft.position.set(-40, -50, 25);
scene.add(lightBottomLeft);
var lightTopRight = new THREE.PointLight(0xffffff, 1, 100);
lightTopRight.position.set(40, 50, 25);
scene.add(lightTopRight);
var lightTopLeft = new THREE.PointLight(0xffffff, 1, 100);
lightTopLeft.position.set(-40, 50, 25);
scene.add(lightTopLeft);
var backLight = new THREE.PointLight(0xffffff, 1, 100);
backLight.position.set(0, 0, -25);
scene.add(backLight);
var light = new THREE.AmbientLight(0x404040, 2); // soft white light
scene.add(light);
// update function
function render() {
requestAnimationFrame(render);
sphere.rotation.x += 0.005;
sphere.rotation.y += 0.005;
sphere.visible = false;
cubeCamera.update(renderer, scene);
sphere.visible = true;
renderer.render(scene, camera);
}
render();
I would like to see a rotating IcosahedronGeometry which reflects an image on the front side. I tried adding a cube camera and pointing it at the PlaneGeometry with an image texture but nothing is reflecting.
I would like to simulate something like this, but it doesn't have to be exactly the same.
The desired result.
3 issues.
you have to call cubeCamera.update before you access cubeCamera.renderTarget.texture
The parameters to CubeCamera are new CubeCamera(near, far, size).
The code had new CubeCamera(75, 1000, 512) which means only things 75 to 1000 units away from the camera would be visible. The image plane you had is 3 units away so would not be visible.
You don't call lookAt with the CubeCamera as it's always looking in all directions.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// RENDERER
var renderer = new THREE.WebGLRenderer({
antialias: true
});
// RENDERER - SIZE OF CANVAS
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor('#ffffff');
document.body.appendChild(renderer.domElement);
// RESPONSIVE RENDERING
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
var groundMaterial = new THREE.MeshPhongMaterial({
shininess: 100,
color: 0xffffff,
specular: 0xffffff
});
const cubeCamera = new THREE.CubeCamera(0.001, 10, 512);
scene.add(cubeCamera);
// GEOMETRY
var geometry = new THREE.IcosahedronGeometry(2, 1);
var material = new THREE.MeshStandardMaterial({
color: 0x98bbbd,
side: THREE.FrontSide,
roughness: 1,
metalness: 0.5,
});
cubeCamera.update(renderer, scene);
material.roughness = 0;
material.metalness = 1;
material.flatShading = true;
material.envMap = cubeCamera.renderTarget.texture;
var sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
// FLOOR
var loader = new THREE.TextureLoader();
var floorTexture = loader.load('https://i.imgur.com/UKBsvV0.jpg');
var floorMaterial = new THREE.MeshBasicMaterial({
map: floorTexture,
side: THREE.BackSide
});
var floorGeometry = new THREE.PlaneGeometry(5, 5, 1, 1);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = 0;
floor.position.x = 0;
floor.position.z = 3;
scene.add(floor);
// CONTROLS
var orbit = new THREE.OrbitControls(camera, renderer.Mesh);
camera.position.z = 5;
// LIGHTS
var topLeftLight = new THREE.PointLight(0xffffff, 1, 1);
topLeftLight.position.set(-50, 50, -25);
scene.add(topLeftLight);
var topRightLight = new THREE.PointLight(0xffffff, 1, 10);
topRightLight.position.set(50, 150, -25);
scene.add(topRightLight);
var lightBottomRight = new THREE.PointLight(0xffffff, 1, 100);
lightBottomRight.position.set(40, -50, 25);
scene.add(lightBottomRight);
var lightBottomLeft = new THREE.PointLight(0xffffff, 1, 100);
lightBottomLeft.position.set(-40, -50, 25);
scene.add(lightBottomLeft);
var lightTopRight = new THREE.PointLight(0xffffff, 1, 100);
lightTopRight.position.set(40, 50, 25);
scene.add(lightTopRight);
var lightTopLeft = new THREE.PointLight(0xffffff, 1, 100);
lightTopLeft.position.set(-40, 50, 25);
scene.add(lightTopLeft);
var backLight = new THREE.PointLight(0xffffff, 1, 100);
backLight.position.set(0, 0, -25);
scene.add(backLight);
var light = new THREE.AmbientLight(0x404040, 2); // soft white light
scene.add(light);
// update function
function render() {
sphere.rotation.x += 0.005;
sphere.rotation.y += 0.005;
sphere.visible = false;
cubeCamera.update(renderer, scene);
sphere.visible = true;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/js/controls/OrbitControls.js"></script>
I should start off by saying I'm new to WebGL and the THREE library. I'm trying to achieve:
Add 2D shapes to a scene (squares, triangles, circles etc)
Shapes can have any size and position
Shapes should have no fill and an outline that scales depending on the shape size
I tried using wireframe:
const geometry = new THREE.BoxGeometry(40, 40, 0);
const material = new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
The above renders the following:
A 3D box with no depth
A non-scalable outline with a set width of 1
A cross through the box
I also tried the same but plotting the points for a 2D shape:
const shapeSize = 100;
const x = -shapeSize / 2;
const y = -shapeSize / 2;
const square = new THREE.Shape();
square.moveTo(x, y);
square.lineTo(x + shapeSize, y);
square.lineTo(x + shapeSize, y + shapeSize);
square.lineTo(x, y + shapeSize);
square.lineTo(x, y);
const geometry = new THREE.ShapeGeometry(square);
const material = new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true,
});
const mesh = new THREE.Mesh(geometry, material);
this.scene.add(mesh);
The above renders:
A 2D box
A non-scalable outline with a set width of 1
A single diagonal line through the box
Can anyone demonstrate how to achieve the scalable outline of just the 2D shape? Do I need to use a shader?
I've just used the code from the example of fat lines:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(0x000000, 0.0);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var points = [
-5, 4, 0, 5, 4, 0, 5, -4, 0, -5, -4, 0, -5, 4, 0
]
var geometry = new THREE.LineGeometry();
geometry.setPositions(points);
matLine = new THREE.LineMaterial({
color: 0x00ffff,
linewidth: 5, // in pixels
dashed: false
});
line = new THREE.Line2(geometry, matLine);
line.computeLineDistances();
line.scale.set(1, 1, 1);
scene.add(line);
render();
function render() {
requestAnimationFrame(render);
matLine.resolution.set(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/WebGL.js"></script>
<script src='https://threejs.org/examples/js/lines/LineSegmentsGeometry.js'></script>
<script src='https://threejs.org/examples/js/lines/LineGeometry.js'></script>
<script src='https://threejs.org/examples/js/lines/LineMaterial.js'></script>
<script src='https://threejs.org/examples/js/lines/LineSegments2.js'></script>
<script src='https://threejs.org/examples/js/lines/Line2.js'></script>
<script src='https://threejs.org/examples/js/lines/Wireframe.js'></script>
I followed the examples page but I cannot get TextGeometry to draw. The program runs without exceptions.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.lookAt(new THREE.Vector3(0, 0, 0));
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var loader = new THREE.FontLoader();
loader.load('fonts/helvetiker_regular.typeface.json', function (font) {
var textGeo = new THREE.TextGeometry('Hello three.js!!!!', {
font: font,
size: 80,
height: 50,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 8,
bevelSegments: 5
});
textmaterial = new THREE.MeshLambertMaterial({ color: 0x00ff00 });
textMesh1 = new THREE.Mesh(textGeo, textmaterial);
scene.add(textMesh1);
});
camera.position.z = 5;
var animate = function () {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();
Can you please point out where the mistake might be?
I want to have shadows, I set as follows, really wondering what's the problem? I have a grid, with cubic and sphere as a child of it, and also I set the castShadow and Receive shadow for them but it has no result for shadow.
some parts of my code:
var camera, scene, renderer, dice, dice1;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(35,window.innerWidth/window.innerHeight, 0.1, 1000);
// Z is up for objects intended to be 3D printed.
camera.up.set(0, 0, 1);
scene.add(camera);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setClearColor(0x999999);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
var light = new THREE.PointLight(0x000000, 1, 1000);
light.position.set(10, 10,10);
light.castShadow = true; // default false
scene.add(light);
//Set up shadow properties for the light;
light.shadow.mapSize.width = 1024; // default
light.shadow.mapSize.height = 1024; // default
light.shadow.camera.near = 1; // default
light.shadow.camera.far = 1000 // default
var grid = new THREE.GridHelper(50, 50, 0xffffff, 0x555555);
grid.colorGrid = 0x00ff00;
grid.rotateOnAxis(new THREE.Vector3(1, 0, 0), 90 * (Math.PI / 180));
scene.add(grid);
objects.push(grid); // add to the array for DragControls
grid.receiveShadow=true;
//Create a sphere that cast shadows (but does not receive them)
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.castShadow = true; //default is false
sphere.receiveShadow = false; //default
sphere.position.set(10, 15, 10);
scene.add(sphere);
//initializing the color cubic
var material = new THREE.MeshBasicMaterial({
color: 0xff0000});
dice = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5, 1, 1, 1), material);
dice.position.set(10, 2.5, 10);
dice.castShadow = true;
grid.add(dice);
You cannot cast shadow on a grid. it is just lines.
Add this in your code to see shadows.
var plane = new THREE.Mesh(new THREE.PlaneGeometry(50,50), new THREE.MeshStandardMaterial( {color: 0x00ff00 }));
plane.castShadow = false;
plane.receiveShadow = true;
plane.position.set(0, 0, -1);
scene.add(plane);