Creating a texture that contains bootstrap doesn't seem to work

Hi, I’m new to three.js and I was testing if it was possible to render some demo bootstrap.css card in to a THREE.CanvasTexture and then apply it to a plane, so I’m doing :

export function createBootstrapCardTexture(cardWidth, cardHeight) {
    // Create a canvas element
    const canvas = document.createElement('canvas');
    canvas.width = cardWidth;
    canvas.height = cardHeight;

    const context = canvas.getContext('2d');
    context.fillStyle = 'white';

    // Create a Bootstrap card
    const card = document.createElement('div');
    card.classList.add('card');
    card.style.width = `${cardWidth}px`; // Set card width
    card.style.height = `${cardHeight}px`; // Set card height
    canvas.appendChild(card);

    // Create card content
    const img = document.createElement('img');
    img.src = 'chuch.png'; // Set your image source
    img.classList.add('card-img-top');
    img.alt = 'chuchiswap';
    card.appendChild(img);

    const cardBody = document.createElement('div');
    cardBody.classList.add('card-body');
    card.appendChild(cardBody);

    const cardTitle = document.createElement('h5');
    cardTitle.classList.add('card-title');
    cardTitle.textContent = 'Card title';
    cardBody.appendChild(cardTitle);

    const cardText = document.createElement('p');
    cardText.classList.add('card-text');
    cardText.textContent = 'Some quick example text to build on the card title and make up the bulk of the card\'s content.';
    cardBody.appendChild(cardText);

    const listGroup = document.createElement('ul');
    listGroup.classList.add('list-group', 'list-group-flush');
    card.appendChild(listGroup);

    const listItems = ['An item', 'A second item', 'A third item'];
    listItems.forEach(itemText => {
        const listItem = document.createElement('li');
        listItem.classList.add('list-group-item');
        listItem.textContent = itemText;
        listGroup.appendChild(listItem);
    });

    const cardBody2 = document.createElement('div');
    cardBody2.classList.add('card-body');
    card.appendChild(cardBody2);

    const cardLink1 = document.createElement('a');
    cardLink1.href = '#';
    cardLink1.classList.add('card-link');
    cardLink1.textContent = 'Card link';
    cardBody2.appendChild(cardLink1);

    const cardLink2 = document.createElement('a');
    cardLink2.href = '#';
    cardLink2.classList.add('card-link');
    cardLink2.textContent = 'Another link';
    cardBody2.appendChild(cardLink2);

    // Convert the canvas to a Three.js texture
    const texture = new THREE.CanvasTexture(canvas);
    texture.matrixAutoUpdate = false;
    texture.flipY = false; // Ensure correct orientation

    return texture;
}

In main.js I do this :

const planeWidth = 2;
const planeHeight = 2;
const planeGeometry = new THREE.PlaneGeometry(planeWidth, planeHeight); // Use THREE.PlaneGeometry


const gridTexture = createBootstrapCardTexture(planeWidth, planeHeight); // Adjust gridSize as needed
console.log(gridTexture)

const gridMaterial = new THREE.MeshBasicMaterial({
    map: gridTexture,
    side: THREE.DoubleSide,
});
  
const gridPlane = new THREE.Mesh(planeGeometry, gridMaterial);
gridPlane.position.set(0, 0, 0);
scene.add(gridPlane);
console.log(gridPlane)

Both function and Mesh return objects, but it doesn’t render. I have made another simple function that doen’t use bootrap ( simply a canvas, a div, and some text ) and it works. Is this actually possible or it’s a limitation ? Or I’m probably doing something really wrong ? Thanks !

Just realized this is not possible. Thanks

1 Like

You’re right. It’s not possible to do with the webGL renderer. You might be able to do it with the CSSRenderer though:

https://threejs.org/examples/?q=css#css3d_periodictable

https://threejs.org/examples/?q=css#css3d_youtube

1 Like

ahh that’s so cool :slight_smile:

I’m going to test it, thanks for pointing out

1 Like

one more question … is it possible to overlay or z-index the CSS3Renderer on top of the WebGLRenderer ? So, as in mixing both renderers ? Note that I don’t need it to be interactive ( clicking links, etc ) but I do need to render the CSS in a frame or as a 3D object and to be able to modify the CSS3 and re-render it on update. I don’t know if there is an example or if it’s possible. Thank you !

EDIT: I found out how to do it here : CSS3DREDNERER object - #6 by cheenou13

Thank you very much, it seems that it’s going to be possible to do what I wanted :smiley:

Yes! Glad to hear!

And yes, overlaying the CSSRenderer on a WebGL renderer is a great use case.
You can even do some fancy stuff by putting the CSS renderer behind the WebGL rendererer and doing some tricks to punch through the webGL revealing the CSS renderer behind it… which lets you make it appear as if the HTML is truly inside your 3d scenes… But it is pretty tricky to implement that, so I’d definitely start with CSS on top until you get comfortable with it.

1 Like