Using Image Cloud Assets as Textures
Introduction
This tutorial demonstrates how to use image-based cloud assets to create textures and apply them to 3D meshes in Bitbybit. To follow along effectively, you should first be familiar with the process of Uploading Cloud Assets.
- Ensure you are signed up and logged into the Bitbybit platform. You can sign up here.
- You should have completed the Uploading Cloud Assets tutorial.
Sample Image for this Tutorial:
Please upload the following image to your project as a cloud asset. Name it dogs-small.jpeg during the upload process (or remember the exact filename you use).
- dogs-small.jpeg (Click to view/download)
Image of dogs that we will use to create a texture and apply it on a 3D mesh
Working with image assets to create textures follows a similar pattern to working with 3D model assets:
- Load the image file from cloud storage.
- Convert or process that file data into a format that Bitbybit's rendering engine (BabylonJS) can understand as a texture.
- Apply this texture to a material.
- Apply the material to a 3D mesh.
General Steps for Using 2D Cloud Assets as Textures
The core process for using an uploaded image as a texture applies across all our editors (Rete, Blockly, and TypeScript). We'll outline these general steps first, then provide specific editor implementations. (Remember, in the visual editors, you can typically find components by following the category path indicators on them.)
-
Load the Image File:
- First, retrieve the image file (e.g.,
dogs-small.jpeg) that you uploaded to your project's cloud assets. This is usually done via a component or function in the "asset" category (e.g., "get cloud file"). This action loads the file data into the browser's memory.
- First, retrieve the image file (e.g.,
-
Create an Object URL:
- Once you have the file data, you need to create an Object URL from it. An Object URL is a special type of URL that provides a temporary, local reference to a file's data stored in the browser's memory. BabylonJS (our 3D engine) can then use this URL to load the image data for a texture.
- This step is crucial because it allows BabylonJS to access the image content without needing a permanent web URL for the image file itself.
- You can learn more about Object URLs from the MDN Web Docs: URL.createObjectURL().
- (Note: An Object URL is only valid within the browser session that created it; it cannot be shared or accessed externally.)
-
Create a BabylonJS Texture:
- Use the generated Object URL as the input (often a
urlproperty) when creating a BabylonJS Texture object.
- Use the generated Object URL as the input (often a
-
Create a Material and Apply Texture:
- Create a BabylonJS Material (e.g., a StandardMaterial).
- Assign the Texture object you created in the previous step to one of the material's texture slots (e.g., the
diffuseTexturefor the main color/image).
-
Create a Mesh and Apply Material:
- Create or load a 3D mesh (e.g., a simple box or plane using BabylonJS mesh builders, or a more complex imported model).
- Assign the Material (which now has your image texture) to this mesh.
BabylonJS mesh builders (like those for creating boxes, spheres, planes) render directly without needing an explicit "Draw" command, as BabylonJS handles their rendering.
-
Position and Enhance (Optional):
- You might want to change the position, rotation, or scale of your meshes to arrange them in the scene.
- The example scripts below also include optional elements like a skybox, lighting, and shadows to make the scene look more appealing. These are not strictly necessary for the texture application itself.
Implementation in the Rete Editor
The Rete editor provides a visual flow that closely mirrors the conceptual steps described above. It tends to hide some of the underlying asynchronous complexities, making the graph appear more direct.
Rete Editor Example:
Implementation in the Blockly Editor
The Blockly implementation will also follow the core principles but might look a bit more involved than Rete due to its more explicit handling of program flow, especially asynchronous operations.
- Asynchronous Handling: Pay attention to how asynchronous code (like file loading) is managed. Often, this involves creating an "async context" (e.g., from a "time" category) within which you can use "Await" blocks. This helps make asynchronous operations behave in a more understandable, sequential manner.
Blockly Editor Example:
Implementation in the TypeScript Editor
TypeScript gives you the most freedom in structuring your code. However, you'll notice that the underlying logic and the sequence of Bitbybit API calls will resemble the steps performed in the visual editors. The example uses functions to improve readability and organization.
- Async/Await: Just like in Blockly,
asyncfunctions and theawaitkeyword are essential for managing operations that take time, such as loading the image file and creating textures.
TypeScript Editor Example:
const start = async () => {
setupEnvironment();
const mat = await setupTextureAndMaterial("dogs-small.jpeg");
createGeometryAndAssignMaterial(mat);
}
async function setupTextureAndMaterial(cloudAssetFileName: string) {
const file = await bitbybit.asset.getFile({
fileName: cloudAssetFileName
});
const objectUrl = bitbybit.asset.createObjectURL({
file
});
const textureOptions = new Bit.Inputs.BabylonTexture.TextureSimpleDto();
textureOptions.url = objectUrl;
const texture = bitbybit.babylon.texture.createSimple(textureOptions);
const materialOptions = new Bit.Inputs.BabylonMaterial.PBRMetallicRoughnessDto();
materialOptions.roughness = 0.9;
materialOptions.metallic = 0.1;
materialOptions.baseColor = "#ffffff";
const mat = bitbybit.babylon.material.pbrMetallicRoughness.create(materialOptions);
mat.baseTexture = texture;
return mat;
}
function createGeometryAndAssignMaterial(mat: BABYLON.PBRMetallicRoughnessMaterial) {
const cubeOptions = new Bit.Inputs.BabylonMeshBuilder.CreateCubeDto();
cubeOptions.size = 10;
const cubeMesh = bitbybit.babylon.meshBuilder.createCube(cubeOptions);
cubeMesh.material = mat;
bitbybit.babylon.mesh.moveUp({
babylonMesh: cubeMesh,
distance: 7,
})
const squarePlaneOptions = new Bit.Inputs.BabylonMeshBuilder.CreateSquarePlaneDto();
squarePlaneOptions.size = 40;
const planeSquareMesh = bitbybit.babylon.meshBuilder.createSquarePlane(squarePlaneOptions);
bitbybit.babylon.mesh.pitch({
babylonMesh: planeSquareMesh,
rotate: 90
})
planeSquareMesh.material = mat;
}
function setupEnvironment() {
const skyboxOptions = new Bit.Inputs.BabylonScene.SkyboxDto();
bitbybit.babylon.scene.enableSkybox(skyboxOptions);
const dirLightOptions = new Bit.Inputs.BabylonScene.DirectionalLightDto();
dirLightOptions.intensity = 5;
bitbybit.babylon.scene.drawDirectionalLight(dirLightOptions);
}
start();
By following these examples, you can effectively use your uploaded image cloud assets to add rich textures and visual detail to your 3D scenes in Bitbybit, regardless of your preferred editor.
