Why is OutlinePass in Three.js causing everything to appear pixelated? - javascript

For some reason, the way I've used OutlinePass in my code causes everything (except the added outline) to be pixelated, but the EffectComposer works fine with just the RenderPass, and I can't figure out why. According to some similar questions and answers I've seen, adding an FXAAShader might solve this, but I tried this (code commented below) and it did not seem to make any difference. What is causing this behaviour?
<script type="importmap">
{
"imports": {
"three": "https://threejs.org/build/three.module.js"
}
}
</script>
<!--
Had to put JS in the HTML block to import THREE
Also, issue is more clear with an image material, but I had to use a solid color for this example
-->
<script type="module">
import * as THREE from "three";
import {EffectComposer} from "https://threejs.org/examples/jsm/postprocessing/EffectComposer.js";
import {OutlinePass} from "https://threejs.org/examples/jsm/postprocessing/OutlinePass.js";
import {RenderPass} from "https://threejs.org/examples/jsm/postprocessing/RenderPass.js";
// import {ShaderPass} from "https://threejs.org/examples/jsm/postprocessing/ShaderPass.js";
// import {FXAAShader} from "https://threejs.org/examples/jsm/shaders/FXAAShader.js";
const windowSize = [256,256],
mesh = new THREE.Mesh(new THREE.BoxGeometry(16,16,16), new THREE.MeshBasicMaterial({color: 0xd41313})),
scene = new THREE.Scene(),
camera = new THREE.OrthographicCamera(-16,16,16,-16),
renderer = new THREE.WebGLRenderer(),
textureLoader = new THREE.TextureLoader(),
effectComposer = new EffectComposer(renderer),
outline = new OutlinePass(new THREE.Vector2(...windowSize), scene, camera);
// const effectFXAA = new ShaderPass(FXAAShader);
// --- Swapping these two passes demonstrates it's the outline causing issues
effectComposer.addPass(new RenderPass(scene, camera));
effectComposer.addPass(outline);
// --- FXAAShader was an attempt to fix it, since some research showed it could be anti-aliasing issues, but this did not seem to make a difference
// effectFXAA.uniforms['resolution'].value.set(1/windowSize[0],1/windowSize[1]);
// effectComposer.addPass(effectFXAA);
renderer.setSize(...windowSize);
camera.position.set(32,32,32);
camera.lookAt(0,0,0);
outline.selectedObjects = [mesh];
scene.add(mesh);
document.body.appendChild(renderer.domElement);
effectComposer.render();
</script>

I had the same issue, then I had to re assign the pixel ratio and the size on the resize window event, and that fixed the problem. (Is even not necessary the FXAAShader to solve the problem)
...
window.addEventListener("resize", this.resize.bind(this));
resize(){
this.composer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
this.composer.setSize(this.width, this.height)
}

Related

How to import an external model in vue.js using babylon js

I am trying to import a gltf file in vue.js using babylon.js and add 3 dimensional view to the webpage. I can't figure out how to do that and the documentation online is pretty vague as well. Here's what I tried:
This is what I put in Hello.vue file
<div>
<h1> Hello </h1>
<Scene>
<Box :position="[0, 0, 5]"></Box>
</Scene>
</div>
</template>
<script src = "./Hello.js">
</script>
This is what I put in Hello.js file
import vb from 'vue-babylonjs';
import Hello from './Hello.vue';
Vue.use(vb);
new Vue({
components: { Hello },
render: c => c('Hello'),
}).$mount('#app');
var delayCreateScene = function () {
// Create a scene.
var scene = new BABYLON.Scene(engine);
// Create a default skybox with an environment.
var hdrTexture = BABYLON.CubeTexture.CreateFromPrefilteredData("../assets/magic_book_of_eden/textures/material_0_baseColor.png", scene);
var currentSkybox = scene.createDefaultSkybox(hdrTexture, true);
// Append glTF model to scene.
BABYLON.SceneLoader.Append("../assets/magic_book_of_eden/", "scene.gltf", scene, function (scene) {
// Create a default arc rotate camera and light.
scene.createDefaultCameraOrLight(true, true, true);
// The default camera looks at the back of the asset.
// Rotate the camera by 180 degrees to the front of the asset.
scene.activeCamera.alpha += Math.PI;
});
return scene;
};
If possible, could someone explain using an example how that could be done? I am getting the gltf model from sketchfab. Thank you!
Output:
I would try importing the file and then use that variable in the SceneLoader.

Three.js - TypeError: THREE.XLoader is not a constructor

So I decided to see if I could import a DirectX Model and found this XLoader. However I can't seem to initialize it at all. Now, I am the kind of guy who likes to link directly to the library so that whenever there is an update I don't have to re-download and re-upload. My test code looks like this:
<html>
<body>
<script src="https://threejs.org/build/three.js"></script>
<script type="module" src="https://threejs.org/examples/jsm/loaders/XLoader.js"></script>
<script>
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.001, 10000 );
var manager = new THREE.LoadingManager();
var Texloader = new THREE.TextureLoader();
var loader = new THREE.XLoader(manager, Texloader);
loader.load(['FrigateHull.x'], function (object) {
console.log(object);
},function (xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log(Math.round(percentComplete, 2) + '% downloaded');
}},
function (xhr) {
console.log(xhr);
});
</script>
</body>
</html>
The error I am getting from this setup is this:
TypeError: THREE.XLoader is not a constructor
I have also tried the import method as described in the examples but still same error. I have also downloaded the git to the server and tried linking to that, but it said something about global is undefined.
What am I missing, or is there another DirectX Model Loader out there I could try?
Should be like this:
<script src="https://threejs.org/build/three.js"></script>
<script type="module">
import { XLoader } from "https://threejs.org/examples/jsm/loaders/XLoader.js";
// ....
var loader = new XLoader(manager, Texloader);
// ....
</script>
Although the TypeError: THREE.XLoader is not a constructor exception is resolved, there are still other problems.
Let's look at the source code of XLoader.js:
import {
AnimationClip,
AnimationMixer,
Bone,
BufferGeometry,
FileLoader,
Float32BufferAttribute,
FrontSide,
Loader,
LoaderUtils,
Matrix4,
Mesh,
MeshPhongMaterial,
Quaternion,
Skeleton,
SkinnedMesh,
TextureLoader,
Uint16BufferAttribute,
Vector2,
Vector3
} from "../../../build/three.module.js";
// ...
We don't have ../../../build/three.module.js code.
It is recommended that you clone the repository of three.js, and then npm install → npm start to start the project, instead of viewing it directly in the browser, which involves a lot of import and export of modules depends on front-end construction tools.

Three.js - OrbitControls doesn't work

If I run the script, the console displays me "THREE.OrbitControls is not a constructor".
What did I wrong? I used the same code from a manual.
var controls;
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
var render = function () {
requestAnimationFrame( render );
renderer.render(scene, camera);
//Hier wird die Größe des Fensters manipuliert!
renderer.setSize(window.innerWidth - 20, window.innerHeight - 20);
};
var animate = function () {
requestAnimationFrame( animate );
controls.update();
};
var geometry1 = new THREE.BoxGeometry( 10, 10, 10);
var material = new THREE.MeshPhongMaterial( {specular: "#fdfb57", color: "#d8d613", emissive: "#6b6a0d", side: THREE.DoubleSide} );
var box = new THREE.Mesh(geometry1, material);
scene.add(box);
camera.position.z = 50;
render();
animate();
You must explicitly include OrbitControls in your application. For example:
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims#1.3.6/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three/build/three.module.js",
"three/addons/": "https://unpkg.com/three/examples/jsm/"
}
}
</script>
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
Also, read the comments in the three.js OrbitControls example carefully so you understand when to use
controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
and when to use
controls.update(); // required if controls.enableDamping = true, or if controls.autoRotate = true
https://github.com/mrdoob/three.js/blob/dev/examples/misc_controls_orbit.html
three.js r.147
I had the same issue with a webpack build of the three library
var THREE = require('three')
THREE.OrbitControls === undefined // true
Solution, install a 3rd party orbit control
npm install three-orbit-controls
details here: https://github.com/mattdesl/three-orbit-controls
then change the above code fragment to
var THREE = require('three')
var OrbitControls = require('three-orbit-controls')(THREE)
OrbitControls === undefined // false
ok, not the best example, but when applied in place of THREE.OrbitControls, it works just fine ;)
https://github.com/nicolaspanel/three-orbitcontrols-ts :
npm install --save three-orbitcontrols-ts
import { OrbitControls } from 'three-orbitcontrols-ts'
orbitcontrols should be installed separately in angular, this issue bothers me for several days.
I have a same problem too, it's because you put in wrong line.
you need to put it under of this line
document.body.appendChild( renderer.domElement );
then you add orbit controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', posUpdate );
controls.update();
if it wasn't work, add the script file download here
<script src="OrbitControls.js"></script>
I faced similar issue and after lot of research, the below thing worked
In your HTML the order matters when adding OrbitControls as it needs certain things from Three.js.
It should be
<script src="../build/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>

How do I get pixi to expand my canvas and zoom in?

I'm making a game that uses pixi and it renders on a canvas that's 640x480 pixels. As you can imagine, this is very small when viewed on a PC. I'd like to accomplish this:
I want to increase the size of the canvas so it fills up the whole screen
I want to zoom in on the content so that it fills up as much as possible without changing its aspect ratio
I'd like to center the canvas if there's left over space from the previous step
When I google for how to do this in pixi, I can find each of these individually. But I'd like to have the information on how to do this all in one place and on stackoverflow, because you usually want to do all of these things together.
I modified the source code in this example made by the creator: http://www.goodboydigital.com/pixi-js-tutorial-getting-started/ (source download)
Here's what I came up with:
<!DOCTYPE HTML>
<html>
<head>
<title>pixi.js example 1</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #000000;
}
</style>
<script src="pixi.js"></script>
</head>
<body>
<script>
// create an new instance of a pixi stage
var stage = new PIXI.Stage(0x66FF99);
// create a renderer instance
var renderer = PIXI.autoDetectRenderer(400, 300);
renderer.resize(800, 600);
// add the renderer view element to the DOM
document.body.appendChild(renderer.view);
requestAnimFrame( animate );
// create a texture from an image path
var texture = PIXI.Texture.fromImage("bunny.png");
// create a new Sprite using the texture
var bunny = new PIXI.Sprite(texture);
// center the sprites anchor point
bunny.anchor.x = 0.5;
bunny.anchor.y = 0.5;
// move the sprite t the center of the screen
bunny.position.x = 200;
bunny.position.y = 150;
var container = new PIXI.DisplayObjectContainer();
container.scale.x = 2;
container.scale.y = 2;
container.addChild(bunny);
stage.addChild(container);
function animate() {
requestAnimFrame( animate );
// just for fun, lets rotate mr rabbit a little
bunny.rotation += 0.1;
// render the stage
renderer.render(stage);
}
</script>
</body>
</html>
Now the one thing I didn't do is center it. I see two potential ways to do this. I could use CSS to center the canvas (what I'll probably use), or I could do this in code by adding another outer display object to the stage that centers container.

Box2d.js impulses/forces and initial position

I was "playing" with kripken's box2d when I had a pair of issues. I chose this fork because it seems to be the fastest and the most used.
API defines position on bodyDef but you 'must' give it on body.
Forces, impulses, ... keep attached to the body giving a unexpected constant velocity.
Does anybody get these behaviours before? Does anybody have any hints?
This comes from a complex app but I have simplified for demo:
<html>
<head>
<script src="http://kripken.github.io/box2d.js/box2d.js"></script>
</head>
<body>
<script>
// gravity 0 for top view scene
var world = new Box2D.b2World( new Box2D.b2Vec2(0, 0), true);
var bodyDef = new Box2D.b2BodyDef();
bodyDef.set_type( Box2D.b2_dynamicBody );
bodyDef.set_position(40,40);
var body = world.CreateBody(bodyDef);
// ISSUE 1
// without these two lines real position is 0,0
body.GetPosition().set_x(40);
body.GetPosition().set_y(40);
var dynamicBox = new Box2D.b2PolygonShape();
dynamicBox.SetAsBox(5.0, 5.0);
var fixtureDef = new Box2D.b2FixtureDef();
fixtureDef.set_shape(dynamicBox);
fixtureDef.set_density(1);
fixtureDef.set_friction( 0.8);
fixtureDef.set_restitution( 0.5);
body.CreateFixture(fixtureDef);
//ISSUE 2
// Never ending movements
//body.ApplyLinearImpulse(new Box2D.b2Vec2(5,5),body.GetWorldCenter());
body.ApplyForce(new Box2D.b2Vec2(50,50),body.GetWorldCenter());
function update() {
world.Step(1/30, 10, 10);
world.ClearForces();
console.log(body.GetPosition().get_x()+","+body.GetPosition().get_x());
}
setInterval(update, 1000/60);
</script>
</body>
</html>
For issue 1, set_position should expect a b2Vec2 parameter. Try this:
bodyDef.set_position( new b2Vec2( 40, 40 ) );
I got more issues so finally I switched to box2dweb. Older but more tested and more stable.

Categories

Resources