I am trying simple spinning cube sample of three.js in enyo framework.
I am getting error as
THREE.WebGLRenderer:Error creating WebGL context.
Here is my code:
enyo.kind({
name:"Cubetest",
create:function () {
// body...
this.inherited(arguments);
this.drawCube();
//alert("in create");
},
rendered : function(){
this.inherited(arguments);
//this.drawCube();
},
drawCube : function(){
var scene = new THREE.Scene();
console.log(scene);
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
console.log(camera);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.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 );
console.log(cube);
console.log(scene);
camera.position.z = 5;
var render = function () {
requestAnimationFrame( render );
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
}
});
What may be problem here?
It supports CanvasRenderer.
If I replace WebGLRenderer by CanvasRenderer,it works fine.
I believe the problem you are running into is that you are appending a DOM node to the body before Enyo has created its DOM nodes. When Enyo creates its nodes, it wipes out the one created by three. You should leave DOM manipulation to Enyo, for the most part.
In Enyo, you do not have a DOM node until after rendered() is called. You should only create the three DOM node within the node created for your kind. You can get the DOM node from Enyo by calling this.hasNode(), which will return the DOM node (or null if rendered() has not been called yet).
Change your method to have three use your kind's node and things should work better.
Related
I'm attempting to use the Magnify-3d package after using an EffectComposer to apply a bokeh effect to a scene. Magnify-3D takes in a renderer, so I cannot simply pass in the EffectComposer after applying passes.
The intended result would work like a microscope, with the ability to independently adjust the plane of focus by adjusting the BokehPass effect, and the magnification using Magnify-3d.
The only way I've gotten this to work so far has been like so:
Create a temporary scene containing actual scene I want to render.
Create an EffectComposer that applies BokehPass and renders the temporary scene to renderTarget.
Create a PlaneBufferGeometry and a mesh that maps renderTarget.texture (the output of the temporary scene) to the plane, and add this to a new scene.
Render the new scene that effectively is just a camera staring at a mesh of the original scene.
Pass the renderer into magnify3d, which creates a lens effect around the scene I want to render.
This seems to work OK (though there appears to be some fuzziness and distortion of the original scene I'm still working out), but I began to wonder -- is this really the best way to use something rendered to a RenderTarget? Is there a more direct way than effectively taking a picture of a picture that I can use to take the output of an EffectComposer, feed it back into a renderer so my final scene is rendered in a WebGLRenderer, and pass it into a library? Any other way I can think to do this, the EffectComposer would not be able to run (since Magnify3d takes in a renderer, not an EffectComposer and I need to run the EffectComposer before passing it into a renderer).
Here's a screenshot of the final result
Here's some code below:
// create initial scene
const renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
const rtScene = new THREE.Scene();
const rtCamera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000000000 );
// add a sample cube to the new scene and move the camera back
const geometry = new THREE.BoxGeometry( 10, 10, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
rtScene.add(cube);
rtCamera.position.z = 500;
// initialize renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 1 );
document.body.appendChild( renderer.domElement );
// initialize EffectComposer and apply BokehEffect.
// Note that composer renders its output to RenderTarget.
const composer = new EffectComposer( renderer, renderTarget );
composer.renderToScreen = false;
const renderPass = new RenderPass( rtScene, rtCamera );
composer.addPass( renderPass );
const bokehValues = {
focus: 500,
aperture: .00025,
maxblur: 1,
width: window.innerWidth,
height: window.innerHeight
}
export const bokehPass = new BokehPass( rtScene, rtCamera, bokehValues);
composer.addPass( bokehPass );
// create final scene to render before passing to Magnify3D
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000000000 );
const scene = new THREE.Scene();
camera.position.z = 100;
// make a plane geometry, a mesh that maps renderTarget.texture, and add it to the scene
const planeGeometry = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
const planeMaterial = new THREE.MeshBasicMaterial( { map: renderTarget.texture } );
const plane = new THREE.Mesh( planeGeometry, planeMaterial );
scene.add( plane );
function animate() {
// first render temporary scene
renderer.setClearColor( 0xffffff, 1 );
composer.render(); // now composer has rendered to renderTarget
renderer.setClearColor( 0x141414, 1 ); // create a black background for outside of microscope
renderer.render( scene, camera ); // render final scene with meshed plane
// Finally use Magnify3D to render final scene with microscope
magnify3d.render({
renderer: renderer,
pos: {
x: window.innerWidth/2,
y: window.innerHeight/2
},
renderSceneCB: (target) => {
if (target) {
renderer.setRenderTarget(target);
} else {
renderer.setRenderTarget(null);
}
renderer.render(scene, camera);
},
radius: window.innerWidth/5,
exp: 150,
zoom: state.magnification,
});
requestAnimationFrame( animate );
}
I am trying to make a THREE.JS scene with GLSL shaders applied, but am having trouble figuring out how to make it load my shaders. The scene appears to work, but the shaders don't do what they're supposed to. I'm using a shader loader function I found that uses pure THREE.JS instead of AJAX or Jquery.
Here is the main javascript for my scene.
var container,
renderer,
scene,
camera,
light,
mesh,
controls,
start = Date.now(),
fov = 30;
window.addEventListener( 'load', function() {
container = document.getElementById( "container" );
if(!Detector.webgl) {
Detector.addGetWebGLMessage(container);
return;
}
//get the width and height
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
//sphere params
var radius = 20,
segments = 4,
rotation = 6;
scene = new THREE.Scene();
// ASPECT RATIO
camera = new THREE.PerspectiveCamera(fov, WIDTH / HEIGHT, 1, 10000);
camera.position.z = 100;
scene.add(new THREE.AmbientLight(0x333333));
light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(100, 3, 5);
scene.add(light);
;
ShaderLoader('./shaders/vertex.vert', './shaders/fragment.frag')
material = new THREE.ShaderMaterial( {
uniforms: {
tExplosion: {
type: "t",
value: THREE.ImageUtils.loadTexture( 'images/explosion.png' )
},
time: { //float initialized to 0
type: "f",
value: 0.0
}
},
vertexShader: ShaderLoader.vertex_text,
fragmentShader: ShaderLoader.fragment_text
} );
mesh = new THREE.Mesh(
new THREE.IcosahedronGeometry( radius, segments ),
material
);
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize( WIDTH, HEIGHT );
renderer.setPixelRatio( window.devicePixelRatio );
//update renderer size, aspect ratio, and projectionmatrix, on resize
window.addEventListener('resize', function() {
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
controls = new THREE.TrackballControls( camera );
container.appendChild( renderer.domElement );
render();
} );
function render() {
material.uniforms[ 'time' ].value = .00025 * ( Date.now() - start );
controls.update();
requestAnimationFrame( render );
renderer.render(scene, camera);
}
// This is a basic asyncronous shader loader for THREE.js.
function ShaderLoader(vertex_url, fragment_url, onLoad, onProgress, onError) {
var vertex_loader = new THREE.XHRLoader(THREE.DefaultLoadingManager);
vertex_loader.setResponseType('text');
vertex_loader.load(vertex_url, function (vertex_text) {
var fragment_loader = new THREE.XHRLoader(THREE.DefaultLoadingManager);
fragment_loader.setResponseType('text');
fragment_loader.load(fragment_url, function (fragment_text) {
onLoad(vertex_text, fragment_text);
});
}, onProgress, onError);
}
But when my scene loads, it is just a red sphere with no lighting or applied shaders... What am I doing wrong? I'm new to all of this so it is probably something easily noticeable for someone more experienced, but I have searched and searched and been experimenting and can't figure it out.
Thanks!
Try to add material.needsUpdate = true after you load your shader.
The snippet show error of the WebGL detector.
Are you loading that library?
https://github.com/mrdoob/three.js/blob/master/examples/js/Detector.js
I want to use the build version of three.js (https://threejs.org/build/three.js) for a project.
I was using an old one version of the library and everything was fine and my mesh (loaded form a .json file) appeared normally.
Here's my code :
var renderer, scene, camera, mesh, material;
initMesh();
function initMesh() {
var controls;
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(0,500,700);
camera.up = new THREE.Vector3(0,0,0);
camera.lookAt(new THREE.Vector3(0,0,0));
scene = new THREE.Scene();
scene.add(camera);
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var loader = new THREE.JSONLoader();
loader.load('test.json', function(geometry) {
material = new THREE.MeshBasicMaterial({ color: 0x00ff84, wireframe: true, wireframeLinewidth: 3 });
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
render();
});
}
var render = function () {
requestAnimationFrame( render );
renderer.render(scene, camera);
};
Here is what I got when using old one library.
I don't see what I miss ? Any idea ? Thank you.
I tried with your example
Removing this line fixed the issue: camera.up = new THREE.Vector3(0,0,0);
I'm new to three.js and need to make a project for school. For this project I need a texture on my cube. But the screen stays black.. and there are no console errors! I did everything I can so this is kinda my last change haha.
My code:
<script src="js/three.min.js"></script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
// +
var material = new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('images/crate2.jpg')
})
// =
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
var render = function () {
requestAnimationFrame( render );
cube.rotation.x += 0.1;
cube.rotation.y += 0.05;
renderer.render(scene, camera);
};
render();
</script>
You do not have a light in your scene.
Adding one like below should work
// Create ambient light and add to scene.
var light = new THREE.AmbientLight(0xffffff); // white light
scene.add(light);
I would add a link to a js fiddle but it seems they have changed and I can not longer find where to get the link.
Anyway, just ad some sort of light.
Perhaps adding a light would help? That or try using THREE.MeshBasicMaterial
I'm trying add subdivisions to a sphere like this:
http://stemkoski.github.com/Three.js/Subdivision-Cube.html
Here's my code: http://jsfiddle.net/mdrorum/HvFLw/
<script src="http://mrdoob.github.com/three.js/build/three.js"></script>
<script type="text/javascript">
var camera, scene, renderer;
var geometry, material, mesh;
var smooth, subdiv, modifier;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 1000;
scene = new THREE.Scene();
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
geometry = new THREE.SphereGeometry( 200 );
material = new THREE.MeshBasicMaterial( { color: 0x00ff00, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var smooth = mesh.clone();
var subdiv = 3;
var modifier = new THREE.SubdivisionModifier( subdiv );
//modifier.modify( smooth );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
</script>
This works fine, but uncomment: //modifier.modify( smooth );
Nothing happens. :(
How I can add subdivisions?
Here you can find a good tutorial with a working demo. Citing the author:
// First we want to clone our original geometry.
// Just in case we want to get the low poly version back.
var smooth = THREE.GeometryUtils.clone( geometry );
// Next, we need to merge vertices to clean up any unwanted vertex.
smooth.mergeVertices();
// Create a new instance of the modifier and pass the number of divisions.
var divisions = 3;
var modifier = new THREE.SubdivisionModifier(divisions);
// Apply the modifier to our cloned geometry.
modifier.modify( smooth );
// Finally, add our new detailed geometry to a mesh object and add it to our scene.
var mesh = new THREE.Mesh( smooth, new THREE.MeshPhongMaterial( { color: 0x222222 } ) );
scene.add( mesh );
You are trying to modify a mesh. You need to modify a geometry.
modifier.modify( geometry );