I'm trying to do some pixel manipulation on a image texture of a loaded 3d model.
So I started drawing the image to canvas to get the image data, and re-apply that image to the model. But it seems it lost all its texture coordinates. How can I preserve them?
This is what I have:
let img = clothes.material.emissiveMap.image;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
ctx.putImageData(imageData, 0, 0);
var new_image = new Image();
new_image.src = canvas.toDataURL();
clothes.material.emissiveMap.image = new_image;
clothes.material.emissiveMap.needsUpdate = true;
clothes.material.needsUpdate = true;
Original
Modified
Thank you for any suggestions
I suggest you use a slightly different workflow:
const img = clothes.material.emissiveMap.image;
const canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
clothes.material.emissiveMap.dispose();
clothes.material.emissiveMap = new THREE.CanvasTexture(canvas);
// copy texture parameters if necessary
It is not intended to change the image reference of an existing texture.
Related
I am trying to have a repeated background image with the text foreground but when I add pattern on canvas the text is not visible, here is me code:
HTML
<canvas id="canvas"></canvas>
JavaScript
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = "https://cdn.pixabay.com/photo/2019/03/03/20/23/flowers-4032775__340.png";
img.height = 10;
img.onload = function(){
ctx.font = "30px Calibri";
ctx.fillText("DEXIE", 10, 50);
ctx.drawImage(img, 0, 0);
var ptrn = ctx.createPattern(img, 'repeat');
ctx.fillStyle = ptrn;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
Draw the text after drawing the pattern. Changing the fillStyle to what color you want the text to be.
canvas.width = innerWidth;
canvas.height = innerHeight;
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = "https://cdn.pixabay.com/photo/2019/03/03/20/23/flowers-4032775__340.png";
img.onload = function(){
img.height = 10;
ctx.drawImage(img, 0, 0); // Do you really want to draw the image on the canvas????
var ptrn = ctx.createPattern(img, 'repeat');
// Draw pattern first
ctx.fillStyle = ptrn;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw text on top
ctx.font = "30px Calibri";
ctx.fillStyle = "Black"; // <<== Set text color
ctx.fillText("DEXIE", 10, 50);
}
I am trying to load a Image from an url and draw it onto a canvas which is used as input for a Texture. I have implemented this on https://jsfiddle.net/9Louwn87/25/ . I have used this following snippet to load the image and create the texture
var img = new Image();
img.onload = function() {
canvas.width = size;
canvas.height = size;
ctx.drawImage(this, 0, 0, size, size);
if(texture)
{
texture.needsUpdate = true;
}
};
img.src = "https://threejsfundamentals.org/threejs/resources/images/wall.jpg";
texture = new THREE.Texture(canvas);
Please can anyone point me to the mistake.
The issue is probably that since you're loading the image yourself and you're loading it from another domain you need to request permission to use the image.
var img = new Image();
img.onload = function() {
canvas.width = size;
canvas.height = size;
ctx.drawImage(this, 0, 0, size, size);
if(texture)
{
texture.needsUpdate = true;
}
};
img.crossOrigin = 'anonymous'; // ----------- Add this line
img.src = "https://threejsfundamentals.org/threejs/resources/images/wall.jpg";
texture = new THREE.Texture(canvas);
note that adding that line does not automatically let you use an image from another website. Rather it asks that website for permission to use the image. Some sites (imgur, flickr, github, threejsfundamentals.org), give that permission. Most sites do not give permission. If the image is on the same domain then you generally do not want to set crossOrigin otherwise unless your server is configured to give permission you won't be able to use local images where as normally if you don't ask then local images just work.
Also, if you had opened the JavaScript console you'd have seen this error
three.min.js:572 Uncaught DOMException: Failed to execute 'texImage2D'
on 'WebGLRenderingContext': Tainted canvases may not be loaded.
One more thing, you can use three.js's ImageLoader which handles this permission issue automatically setting crossDomain if the image is on another domain and not setting it if it's local.
const loader = new THREE.ImageLoader();
loader.load("https://threejsfundamentals.org/threejs/resources/images/wall.jpg", function() {
canvas.width = size;
canvas.height = size;
ctx.drawImage(this, 0, 0, size, size);
if(texture)
{
texture.needsUpdate = true;
}
});
This is how I set in my code
createText(text = 'example') {
const canvas = document.createElement('canvas');
// canvas.width = 256;
// canvas.height = 64;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#796e8c';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font='120px Arial';
ctx.fillStyle = '#000000';
ctx.fillText(text, 0, 120);
const canvasTexture = new THREE.CanvasTexture(canvas);
const spriteMaterail = new THREE.SpriteMaterial({
map: canvasTexture,
color: 0xffffff
});
const sprite = new THREE.Sprite(spriteMaterail);
return sprite;
}
but the context is clipped
if I set canvas size like:
canvas.width = 256
canvas.width = 64
the result is like this:
i am trying to add add text (water mark) in canvas generated image
here is my code.
html2canvas($("#frame"), {
onrendered: function (canvas) {
$("#outputImage").html(canvas);
}
what i should add in this code to add watermark mark in generated image
Inside the handler do the following:
html2canvas($("#frame"), {
onrendered: function (canvas) {
var ctx = canvas.getContext("2d"); // get 2D context of canvas
ctx.textBaseline = "top"; // start with drawing text from top
ctx.font = "20px sans-serif"; // set a font and size
ctx.fillStyle = "red"; // set a color for the text
ctx.fillText("WATERMARK", 20, 20); // draw the text at some position (x, y)
$("#outputImage").html(canvas);
}
}
There is also alignment modes using:
ctx.textAlign = "center"; // default: "start" = left-to-right/right-to-left
// depending on language, override with "left" or "right"
Check out Canvas.globalCompositeOperation. If you set it to the string 'lighter', it will lighten the pixels drawn by the next drawing command (such as fillText()). Here's a sample
<canvas id='canvas'></canvas>
<script>
var img = new Image();
img.src = 'http://www.javascripture.com/pic.jpg';
img.onload = function() {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0, canvas.width, canvas.height);
// Draw the Watermark
context.font = '48px sans-serif';
context.globalCompositeOperation = 'lighter';
context.fillStyle = '#444';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.fillText('watermark', canvas.width / 2, canvas.height / 2);
};
</script>
I need to get the color of an image texture on a mesh at a given xyz point (mouse click + ray cast). How can I achieve it in THREE.js?
I know I could use gl.readPixels from plain webgl, but it's not a valid option for me.
Thanks!
So I ended using a separate canvas, in which I load the image texture, translate the three.js coordinates into canvas one and read the pixel. Something like this:
// point is a THREE.Vector3
var getColor = function(point, callback) {
var img = new Image();
img.src = 'assets/img/myImage.png';
img.onload = function() {
// get the xy coords from the point
var xyCoords = convertVector3ToXY(point);
// create a canvas to manipulate the image
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
// get the pixel data and callback
var pixelData = canvas.getContext('2d').getImageData(x, y, 1, 1).data;
callback(pixelData);
}
};
Thanks