I searched and tried some answers about it but it doesn't work.
i tried like this:
var renderer = new THREE.WebGLRenderer( { alpha: true } );
and
root.renderer.setClearColor(0xffffff,0);
as i said it does not work i just saw black screen :/
here is my "init" function :
function init() {
var root = new THREERoot({
createCameraControls:false,
antialias: true,
fov:60
});
root.renderer.setClearColor(0xffffff);
root.renderer.setPixelRatio(window.devicePixelRatio || 1);
root.camera.position.set(0, 0, 400);
var textAnimation = createTextAnimation();
textAnimation.position.y = -40;
root.scene.add(textAnimation);
var tl = new TimelineMax({
repeat:-1,
repeatDelay:0.25,
yoyo:true
});
tl.fromTo(textAnimation, 4,
{animationProgress:0.0},
{animationProgress:1.0, ease:Power1.easeInOut},
0
);
createTweenScrubber(tl);
}
this is what i am using :
https://codepen.io/zadvorsky/pen/xVrMMO
In order for your Three.js project to be transparent, you need to set its renderer's alpha parameter to true:
this.renderer = new THREE.WebGLRenderer({alpha: true});
This way, the parts that don't render anything will show the background of your HTML page, so if your HTML background is #ff0000, then you should see red.
However, you're essentially disabling the transparency when you perform
root.renderer.setClearColor(0xffffff);
This line paints a white background on every frame, which means it's no longer transparent.
Also, I can't see your renderer.render(scene, camera); line, because your code example is so narrow in scope.
Related
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)
}
I'm very new to A-frame and doing a project for my class that requires me to take a 2D image and use it in a 3D scene in whatever way I can come up with. For my project, I want the image to be displayed on multiple boxes, but only on the side that the camera sees first. Anytime I link an image to a shape, it will cover the whole shape as a texture. Is there a way to specify where it can show up on the shape?
There is a component which allows you to use different materials for each side of a cube.
If You're interested in doing it by yourself then you could write a component which would
load the texture
create an array of six materials (one for each side) by only one textured
use the array as the material of the cube
Like this:
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
AFRAME.registerComponent("foo", {
schema: {
img: {type: "selector"}
},
init: function() {
// wait until the entity is loaded
this.el.addEventListener("loaded", evt => {
// grab the mesh
const mesh = this.el.getObject3D("mesh");
// load the texture
this.el.sceneEl.systems.material.loadTexture(this.data.img, {
src: this.data.img
},
// when loaded, create 6 materials for each side
function textureLoaded(texture) {
var cubeMaterial = [
//left
new THREE.MeshBasicMaterial({map: texture}),
//right
new THREE.MeshBasicMaterial({color: 'orange'}),
// top
new THREE.MeshBasicMaterial({color: 'green'}),
// bottom
new THREE.MeshBasicMaterial({color: 'blue'}),
// front
new THREE.MeshBasicMaterial({olor: 'pink'}),
//back
new THREE.MeshBasicMaterial({color: 'yellow'})
];
// apply the new material + clean up the old one
var oldMaterial = mesh.material;
mesh.material = cubeMaterial;
oldMaterial.dispose()
});
});
}
})
</script>
<a-scene>
<a-assets>
<img id="lobster" src="https://i.imgur.com/wjobVTN.jpeg" crossorigin="anonymous" />
</a-assets>
<a-box position="-1 0.5 -3" rotation="45 -45 0" foo="img: #lobster"></a-box>
</a-scene>
if you try to find out on which side of the cube is your camera, then you can change the array, or add / remove the map attribute.
'm working on an application which allows to make image processing, so I used Javascript and PixiJS library to make it possible. I wanted to update cursor image when canvas was hovered
first solution I tried to use cursor: url(cursor1.png) 4 12, auto; but I can't resize cursor. The default size is 64px and I can't set another value.
second solution I decided to add into DOM and update x,y position using Javascript but I got latency.
third solution was to integrate cursor inside my canvas.
last solution I tried to split actions into 2 canvas. The first deals with image processing and the second is my cursor.
With all propositions made before I got loss of FPS when canvas is hovered excepted the first one.
Init main canvas for image processing
function _initMainCanvas(imgData) {
let newCanvas = new PIXI.Application({
width: imgData.width,
height: imgData.height,
transparent: true
});
let blurContainer = new PIXI.Container();
filters.initFilters();
// ----------------------------------------------------------------------------------------
// Normal Sprite
// ----------------------------------------------------------------------------------------
let bg = main.createSprite({
from: imgData.img,
interactive: true,
filters: [filters.getFilterSharpen(), filters.getFilterAdjustment()],
width: imgData.width,
height: imgData.height
});
newCanvas.stage.addChild(bg);
//$(".blur_cursor").remove();
// ----------------------------------------------------------------------------------------
// Blur Sprite
// ----------------------------------------------------------------------------------------
let bgBlured = main.createSprite({
from: imgData.img,
interactive: false,
filters: filters.getFilters(),
width: imgData.width,
height: imgData.height
});
blurContainer.addChild(bgBlured);
blurContainer.mask = containers.getBlurs();
newCanvas.stage.addChild(blurContainer);
newCanvas.stage.addChild(blurContainer);
select.initSelectionRect();
newCanvas.stage.addChild(select.getSelectionRect());
canvas.addMainCanvas(newCanvas);
document.getElementById("container").appendChild(newCanvas.view);
}
Init canvas for cursor update when mouse hover it
function _initCursorCanvas(imgData) {
let cursorCanvas = new PIXI.Application({
width: imgData.width,
height: imgData.height,
transparent: true
});
_fillCursorCanvas(cursorCanvas);
canvas.addCursorCanvas(cursorCanvas);
document.getElementById("container").appendChild(cursorCanvas.view);
}
function _fillCursorCanvas(cursorCanvas) {
// emptySprite allows to bind events
let emptySprite = new PIXI.Sprite();
emptySprite.interactive = true;
emptySprite.width = cursorCanvas.screen.width;
emptySprite.height = cursorCanvas.screen.height;
cursorCanvas.stage.addChild(emptySprite);
emptySprite
.on("pointerdown", canvasEvents.handlerMousedown)
.on("pointerup", canvasEvents.handlerMouseup)
.on("pointermove", canvasEvents.handlerMousemove)
.on("pointerout", canvasEvents.handlerMouseout);
const scale = W / canvas.getWidth();
const cursorTexture = new PIXI.Texture.from(
urlManager.replace("index.php/", "") + "assets/images/cursor_img/50.png"
);
let circle = new PIXI.Sprite(cursorTexture);
circle.width = 50 / scale;
circle.height = 50 / scale;
cursorCanvas.stage.addChild(circle);
}
Mousemove event
const x = e.data.global.x;
const y = e.data.global.y;
cursor.updatePosition(x, y, W);
Will anyone know how to optimize FPS on mouse flying, thank you in advance !
Why do you need a second canvas just for that?
If you want to update the cursor do it at the end of the update loop and that's it, don't make a new canvas just for that.
I was trying to use a canvas as texture in my aframe project. I found some instructions here. It mentioned:
The texture will automatically refresh itself as the canvas changes.
However, I gave it a try today and the canvas could only be changed / updated in init function. Afterwards the update to canvas cannot be reflected. Here is my implementation:
module.exports = {
'canvas_component': {
schema: {
canvasId: { type: 'string' }
},
init: function () {
this.canvas = document.getElementById(this.data.canvasId);
this.ctx = this.canvas.getContext('2d');
this.ctx.fillStyle = "#FF0000";
this.ctx.fillRect(20, 20, 150, 100);
setTimeout(() => {
this.ctx.fillStyle = "#FFFF00";
this.ctx.fillRect(20, 20, 150, 100);
}, 2000);
}
}
The color change of of the texture was never changed. Is there anything I missed? Thank you so much for any advice.
I could never get it to work with those instructions (never checked out if bug or improper use though), but you can achieve the same with Three.js:
// assuming this is inside an aframe component
init: function() {
// we'll update this manually
this.texture = null
let canvas = document.getElementById("source-canvas");
// wait until the element is ready
this.el.addEventListener('loaded', e => {
// create the texture
this.texture = new THREE.CanvasTexture(canvas);
// get the references neccesary to swap the texture
let mesh = this.el.getObject3D('mesh')
mesh.material.map = this.texture
// if there was a map before, you should dispose it
})
},
tick: function() {
// if the texture is created - update it
if (this.texture) this.texture.needsUpdate = true
}
Check it out in this glitch.
Instead using the tick function, you could update the texture whenever you get any callback from changing the canvas (mouse events, source change).
The docs are out of date, I've made a pull request to update them. Here is the code that shows how to do it now:
src: https://github.com/aframevr/aframe/issues/4878
which points to: https://github.com/aframevr/aframe/blob/b164623dfa0d2548158f4b7da06157497cd4ea29/examples/test/canvas-texture/components/canvas-updater.js
We can quickly turn that into a component like this, for example:
/* global AFRAME */
AFRAME.registerComponent('live-canvas', {
dependencies: ['geometry', 'material'],
schema: {
src: { type: "string", default: "#id"}
},
init() {
if (!document.querySelector(this.data.src)) {
console.error("no such canvas")
return
}
this.el.setAttribute('material',{src:this.data.src})
},
tick() {
var el = this.el;
var material;
material = el.getObject3D('mesh').material;
if (!material.map) {
console.error("no material map")
this.el.removeAttribute('live-canvas')
return;
}
material.map.needsUpdate = true;
}
});
(remember to declate your components before your scene...)
usage:
<body>
<canvas id="example-canvas"></canvas>
<a-scene>
<a-box live-canvas="src:#example-canvas;"></a-box>
</a-scene>
</body>
live glitch code demo here:
https://glitch.com/edit/#!/live-canvas-demo?path=index.html%3A58%3A43
You can of course be more efficient than a tick handler if you just intentionally run the equivalent code manually whenever you update the canvas yourself, if that makes more sense / isn't happening frame-by-frame.
I can make a obj to use the canvas to draw like this:
MyObj.myDiv = new Canvas($("effectDiv"), Setting.width, Setting.height);
Then, I use this to draw a rectangle on the canvas:
var c = new Rectangle(80, 80,
{
fill: [220, 40, 90]
}
);
var move = new Timeline;
move.addKeyframe(0,
{
x: 0,
y: 0
}
);
c.addTimeline(move);
MyObj.myDiv.append(c);
But after I draw the rectangle, I want clear the canvas, but I don't know which method and how to do this... ...
O...one more thing:
it is the CAKE's web site:
Link
Clearing the canvas:
canvas.clear = true; // makes the canvas clear itself on every frame
canvas.fill = somecolor; // fills the canvas with some color on every frame
// with canvas.clear = false and low-opacity fill, fancy motion blur effect
Removing the rectangle from the canvas:
rectangle.removeSelf();
or
canvas.removeChild(rectangle);
You can try this method:
MyObj.myDiv.clearRect(0, 0, canvas.width, canvas.height);
Which effectively colours the entire canvas in the background colour.
Easiest way is:
MyObj.myDiv.width = MyObj.myDiv.width;
I found that resizing the canvas works like magic, even if you're not really changing the size:
canvas.width = canvas.width