Drawing Text to the canvas using three.js - asp.net-mvc

To start, I am not the most advanced javascript developer. I have only now started to undertake a more serious study of the subject.
So one of my first forays in this subject is to draw some text to the canvas using the three.js library.But for the life of me, I can't get this sucker to work. I have looked on google and even through the three.js documentation. When I inspect the page in chrome, the page doesn't show any errors either. Here is my code for reference:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth /
window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor(0xdddddd);
var spotlight = new THREE.SpotLight(0xffffff,);
spotlight.castShadow = true;
spotlight.position.set(30,60,60);
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: 5,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 8,
bevelSegments: 5
} );
var color = new THREE.Color();
color.setRGB(255, 250, 250);
textGeo.computeBoundingBox();
textGeo.computeVertexNormals();
var textMaterial = new THREE.MeshBasicMaterial({ color: color });
var mesh = new THREE.Mesh(textGeo, textMaterial);
mesh.position.x = textGeo.boundingBox.max.x / 2;
mesh.position.y = textGeo.boundingBox.max.y / 2;
mesh.castShadow = true;
scene.add(mesh);
} );
var render = function (){
requestAnimationFrame(render);
renderer.render(scene, camera);
}
camera.lookAt(scene.position);
render();
Also, for some background if it's needed, I am running this in debug mode in an asp.net application.
Thanks everyone.

I had my camera directly on the scene, so I couldn't see anything. Thanks prisoner for comment.

Related

PDF.js displays PDF documents in really low resolution/ blurry almost. Is this how it is?

I am trying to use PDF.js to view PDF documents. I find the display really low resolutions to the point of being blurry. Is there a fix?
// URL of PDF document
var url = "https://www.myFilePath/1Mpublic.pdf";
// Asynchronous download PDF
PDFJS.getDocument(url)
.then(function(pdf) {
return pdf.getPage(1);
})
.then(function(page) {
// Set scale (zoom) level
var scale = 1.2;
// Get viewport (dimensions)
var viewport = page.getViewport(scale);
// Get canvas#the-canvas
var canvas = document.getElementById('the-canvas');
// Fetch canvas' 2d context
var context = canvas.getContext('2d');
// Set dimensions to Canvas
canvas.height = viewport.height;
canvas.width = viewport.width;
// Prepare object needed by render method
var renderContext = {
canvasContext: context,
viewport: viewport
};
// Render PDF page
page.render(renderContext);
});
There are two things you can do. I tested and somehow it worked, but you will get a bigger memory consumption.
1 . Go to pdf.js and change the parameter MAX_GROUP_SIZE to like 8192 (double it for example) . Be sure to have your browser cache disable while testing.
You can force the getViewport to retrieve the image in better quality but like, I don't know how to say in English, compress it so a smaller size while showing:
// URL of PDF document
var url = "https://www.myFilePath/1Mpublic.pdf";
// Asynchronous download PDF
PDFJS.getDocument(url)
.then(function(pdf) {
return pdf.getPage(1);
})
.then(function(page) {
// Set scale (zoom) level
var scale = 1.2;
// Get viewport (dimensions)
var viewport = page.getViewport(scale);
// Get canvas#the-canvas
var canvas = document.getElementById('the-canvas');
// Fetch canvas' 2d context
var context = canvas.getContext('2d');
// Set dimensions to Canvas
var resolution = 2 ; // for example
canvas.height = resolution*viewport.height; //actual size
canvas.width = resolution*viewport.width;
canvas.style.height = viewport.height; //showing size will be smaller size
canvas.style .width = viewport.width;
// Prepare object needed by render method
var renderContext = {
canvasContext: context,
viewport: viewport,
transform: [resolution, 0, 0, resolution, 0, 0] // force it bigger size
};
// Render PDF page
page.render(renderContext);
});
enter code here
Hope it helps!
This code will help you, my issue was pdf was not rendering in crisp quality according with the responsiveness. So i searched , and modified my code like this. Now it works for rendering crisp and clear pdf according to the div size you want to give. `var loadingTask = pdfjsLib.getDocument("your_pdfurl");
loadingTask.promise.then(function(pdf) {
console.log('PDF loaded');
// Fetch the first page
var pageNumber = 1;
pdf.getPage(pageNumber).then(function(page) {
console.log('Page loaded');
var container = document.getElementById("container") //Container of the body
var wrapper = document.getElementById("wrapper");//render your pdf inside a div called wrapper
var canvas = document.getElementById('pdf');
var context = canvas.getContext('2d');
const pageWidthScale = container.clientWidth / page.view[2];
const pageHeightScale = container.clientHeight / page.view[3];
var scales = { 1: 3.2, 2: 4 },
defaultScale = 4,
scale = scales[window.devicePixelRatio] || defaultScale;
var viewport = page.getViewport({ scale: scale });
canvas.height = viewport.height;
canvas.width = viewport.width;
var displayWidth = Math.min(pageWidthScale, pageHeightScale);;
canvas.style.width = `${(viewport.width * displayWidth) / scale}px`;
canvas.style.height = `${(viewport.height * displayWidth) / scale}px`;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function() {
console.log('Page rendered');
});
});
}, function(reason) {
// PDF loading error
console.error(reason);
});`

three.js preserveDrawingBuffer not working on iOS

I am rendering a particle system that leaves trails behind. It's working in every browser except on iOS, both safari and chrome. The particles move but the canvas appears to be cleared on every frame, meaning that only the current particles can be seen instead of the history.
I have preserveDrawingBuffer set to true in the render options, so the canvas should not be cleared.
function setup() {
camera = new THREE.OrthographicCamera( canvasSize.width / - 2, canvasSize.width / 2, canvasSize.height / 2, canvasSize.height / - 2, 0.1, 10000 );
camera.position.set(0, 0, -10);
scene = new THREE.Scene();
var material = new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors,
opacity: 0.1,
transparent: true,
linewidth: 1
})
for (var i = 0; i < settings.agents; i++) agents.push(new Agent(i, agentDefaults, canvasSize, limits, geometry, colorMixer))
var line = new THREE.LineSegments(geometry, material);
scene.add(line);
renderer = new THREE.WebGLRenderer({
preserveDrawingBuffer: true,
antialias: true,
alpha: true,
});
renderer.setClearColor(0xffffff, 0)
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(canvasSize.width, canvasSize.height)
renderer.sortObjects = false
renderer.autoClearColor = false
camera.lookAt(scene.position)
settings.container.appendChild(renderer.domElement);
}
function draw() {
for (var i = 0; i < agents.length; i++) {
agents[i].update()
}
geometry.verticesNeedUpdate = true;
geometry.colorsNeedUpdate = true
renderer.render(scene, camera)
requestAnimationFrame(draw)
}
Am I missing a particular command specific to iOS?
The problem is in the renderer, iOS doesn't support anti-aliasing. For some reason this breaks the preserveDrawingBuffer option. So remove antialias: true from your render setup.
renderer = new THREE.WebGLRenderer({
preserveDrawingBuffer: true,
// antialias: true,
alpha: true,
});
https://github.com/mrdoob/three.js/issues/7655

Three.js: Why does the size of CanvasRenderer affect performance on iPhone5s' browsers(chrome, safari)

I am trying to use Three.js to make some graphics. At the beginning stage, I found out: till now on ios7.0, I cannot use WebGL. So instead, I use CanvasRenderer. However, it seems that the size of CanvasRenderer will seriously affect the performance. Could someone give share some thoughts? Or provide a good resolution for CanvasRenderer on ios devices?
Note: I displayed the resolution of chrome on the iPhone5s: 980x1544.
If I set resolution to 640*1024, it works fine.
If I use smaller resolution: (window.innerWidth/2 , window.innerHeight/2), that works fine as well.
However, if I use full width and full height, the cube will not display. Even if I set height to (640,1025), the spinning cube will be really slow.
My question is : how does the size of CanvasRenderer impact on the performance? (Specifically for iPhone5 browsers in this case)
The following is the simple code I wrote to render a cube:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(40, window.innerWidth/window.innerHeight, 0.1, 1000);
document.getElementById("debug").innerHTML = window.innerWidth + " " + window.innerHeight;
renderer = webglAvailable() ? new THREE.WebGLRenderer() : new THREE.CanvasRenderer();
renderer.setSize(640, 1024);
document.getElementById("body").appendChild(renderer.domElement);
var geometry = new THREE.BoxGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 10;
var render = function () {
requestAnimationFrame(render);
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
For reference, you could try to use your iPhone to load these two pages. You can easily see the performance difference.
Resolution 640*1024: http://shawnfandev.com/Testing/workingResolution/Cube.php
Resolution 640*1200: http://shawnfandev.com/Testing/higherResolution/Cube.php
Any thoughts is appreciated!
I made a simple simulation that can change resolution and calculates FPS.
The simulation renders 100 cubes to lower FPS to make it easy to compare.
FPS monitor is provided by stats.js.
This is jsfiddle.
HTML:
<div id="renderer"></div>
<div id="input_fileds">
width: <input type="text" id="width" value="200">
height: <input type="text" id="height" value="200">
</div>
javascript:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(40, 1, 0.1, 1000);
var renderer = new THREE.CanvasRenderer();
renderer.setSize(200, 200);
container = document.getElementById('renderer');
document.body.appendChild(container);
container.appendChild(renderer.domElement);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild(stats.domElement);
var geometry = new THREE.BoxGeometry(.3, .3, .3);
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var cubes = [];
for (var i = 0; i < 100; i++) {
var cube = new THREE.Mesh(geometry, material);
cube.position.x = Math.random() * 6 - 3;
cube.position.y = Math.random() * 6 - 3;
cubes.push(cube);
scene.add(cube);
}
camera.position.z = 10;
var render = function() {
cubes.forEach(function(cube) {
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
});
stats.update();
renderer.render(scene, camera);
setTimeout(render, 1000 / 60);
};
render();
var width_input = document.getElementById('width');
var height_input = document.getElementById('height');
width_input.addEventListener("keyup", function() {
resize();
});
height_input.addEventListener("keyup", function() {
resize();
});
function resize() {
camera.aspect = width_input.value / height_input.value;
camera.updateProjectionMatrix();
renderer.setSize(width_input.value, height_input.value);
}
css:
#renderer{
margin-top:50px;
}
#renderer canvas{
background-color: #000000;
}
#input_fileds{
position:fixed !important;
top:0px;
padding-left:100px;
}
#stats{
position:fixed !important;
}
Result on my iPhone5s
19 FPS on 600x600
19 FPS on 800x800
19 FPS on 1000x1000
19 FPS on 1024x1024
5 FPS on 1025x1025
FPS and resolution are not directly proportional to each other, but when resolution is greater than some point, FPS falls sharply.

In Three.js, lights don't work

I've been fooling around with Three.js for a while, and I don't seem to be able to get any sort of lights to work. The scene renders normally with the 0xFFFFFF ambient lighting, but adding lights doesn't have any effect. I've copied the code directly from the examples and the lights are listed in the children of scene, only not showing up...
var camera;
var scene;
var renderer;
$(document).ready(function() {
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 600;
scene = new THREE.Scene();
scene.add(new THREE.PointLight(0xFF0000, 3.0, 1000));
renderer = new THREE.WebGLRenderer();
//renderer = new THREE.CanvasRenderer();
renderer.domElement.id = "canvas";
renderer.setSize(window.innerWidth, window.innerHeight);
$(window).resize(function() {
renderer.setSize(window.innerWidth, window.innerHeight);
});
$("#container").get(0).appendChild(renderer.domElement);
function Animate() {
requestAnimationFrame(Animate);
renderer.render(scene, camera);
}
Animate();
});
Your code does not give much to work with, but one thing to check is that your materials support lights. That means you should be using MeshLambertMaterial or MeshPhongMaterial. Also note that if you are using a custom ShaderMaterial, it does not magically get scene lighting.

THREE.JS Shadow on opposite side of light

I used THREE.js r49 create 2 cube geometry with a directional light to cast shadow on them and got result as in the following picture.
I noticed that the shadow in the green circle should not be appeared, since the directional light is behind both of the cube. I guess that this is the material issue, I've tried changing various material parameters as well as change the material type itself, but the result still the same. I also tested the same code with r50 and r51 and got the same result.
Could anybody please give me some hint how to get rid of that shadow.
Both cube are creating using CubeGeometry and MeshLambertMaterial as following code.
The code:
// ambient
var light = new THREE.AmbientLight( 0xcccccc );
scene.add( light );
// the large cube
var p_geometry = new THREE.CubeGeometry(10, 10, 10);
var p_material = new THREE.MeshLambertMaterial({ambient: 0x808080, color: 0xcccccc});
var p_mesh = new THREE.Mesh( p_geometry, p_material );
p_mesh.position.set(0, -5, 0);
p_mesh.castShadow = true;
p_mesh.receiveShadow = true;
scene.add(p_mesh);
// the small cube
var geometry = new THREE.CubeGeometry( 2, 2, 2 );
var material = new THREE.MeshLambertMaterial({ambient: 0x808080, color: Math.random() * 0xffffff});
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0, 6, 3);
mesh.castShadow = true;
mesh.receiveShadow = true;
// add small cube as the child of large cube
p_mesh.add(mesh);
p_mesh.quaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), 0.25 * Math.PI );
// the light source
var light = new THREE.DirectionalLight( 0xffffff );
light.castShadow = true;
light.position.set(0, 10, -8); // set it light source to top-behind the cubes
light.target = p_mesh // target the light to the large cube
light.shadowCameraNear = 5;
light.shadowCameraFar = 25;
light.shadowCameraRight = 10;
light.shadowCameraLeft = -10;
light.shadowCameraTop = 10;
light.shadowCameraBottom = -10;
light.shadowCameraVisible = true;
scene.add( light );
Yes, this is a known, and long-standing, WebGLRenderer issue.
The problem is that the dot product of the face normal and the light direction is not taken into consideration in the shadow calculation. As a consequence, "shadows show through from the back".
As a work-around, you could have a different material for each face, with only certain materials receiving shadows.
three.js r.71

Resources