Click events on 3D Objects

Hi jan,

Is there any update going to come, in which we can change the 3d models at run time?
Like for example if we want to see different sofa option at run time.

Is there any possibility of it?

Hi @cningoo, we don’t work on this now, but very likely will be adding such feature this year.


Hello @jan
Is it feasible in the webgl combined render? Only for individual objects - dynamic lighting and shadows?

Hi @Vladan What do you mean by the combined render? The editable objects feature that @cningoo asks about is not available yet. When it is added, it will most likely be done gradually, first the editable objects won’t be casting shadows, but we will be experimenting with dynamic lighting that works well with architectural scenes and WebGL.

Hi @jan , is it possible to put labels on material picker, when selecting materials thru API like this:

or any other way to put the labels on material picker, thank you!

@Half_stack it is not possible to add labels, but please see this post: Material name under Sample - #5 by jan for an explanation how to add a text popup with a selected material name.

1 Like

Thanks @jan , I think that would be the path I’m gonna follow cause it would be easy.

But I would just like to ask, I also did a custom menu, using the material picker api, please see screenshot:

but I encountered some issues, so I stop working it out lol:
-like making the dimensions of the textures with the multiple of 64px, cause when I use a different dimension it render the texture dark.
-and when I tried the following code by adding roughness, metallic, bump., it stops working
var material = viewer.findMaterial(areaToChange);
material.baseColorTexture = texture;
material.roughnessTexture = 0.02;
material.metallicTexture = 1;
material.bumpTexture = 0.01;

Thank you @jan really appreciate the help

Looks really nice!

WebGL requires textures that repeat (like floor tiles) to have power of 2 dimensions. Textures that do not repeat are not required to be power of two, but it looks like the API doesn’t configure such textures correctly. Until we have a fix for this you will see a black result even for not repeating textures.

Anyway, having all textures sizes power of two is the best approach. You can use ImageMagick to resize textures:

convert some-texture.jpg -resize 512x512  some-texture_power_of_two.jpg

To assign scalar values, do not use the Texture suffix:

material.roughness = 0.02;
material.metallic = 1.0;
material.bumpScale = 0.01; // This only has effect if material.bumpTexture is set.

For now, after such changes you will need to call:

1 Like

Jan, regarding the power of two.
How about adding the image upscale function for non-power of two images (in case of the equal width and height)?
I have added a custom override function to the WALK.TextureLoader
Here is the code that seems to be working for me.

function upscaleImg(a) {
var targetWidth = nextHighestPowerOfTwo(a.width);
var targetHeight = nextHighestPowerOfTwo(a.height);
var canvas = document.createElement(“canvas”);
canvas.width = targetWidth;
canvas.height = targetHeight;
var ctx = canvas.getContext(“2d”);
ctx.drawImage(a.image, 0, 0, targetWidth, targetHeight);
a.image = canvas;
ctx = null;
canvas = null;
console.log("image was upscaled to " + targetWidth + "px by " + targetHeight);

function nextHighestPowerOfTwo(x) {
for (var i = 1; i < 32; i <<= 1) {
x = x | x >> i;
return x + 1;

I think we can add such automatic scaling to the API call. It has slight disadvantage of hiding this operation from the API user (such scaling is not super cheap, so whenever possible using already scaled textures is better).

I’m only using it for the customized material picker function. In my case, I have a lot of materials that need to be loaded dynamically, after the Scene initialization. They all have resolution of 800x800px. I know that I can do the server-side scaling for the images, but I prefer for the browsers to do the work to reduce unnecessary server load.
May be if upscaling would be an optional feature, that would be nice. I agree that for the static materials there is no point of doing that.


Really appreciate the help, just want to ask where do I upload the textures? currently they are on my local machine.

Also, for this one, : Detect which material was selected by the user and show the material name. · GitHub
Is there a way to show the material.basetextures, instead of the ?

Thank you again!

@Half_stack the use case that we had in mind for createTextureFromHTMLImage is to allow setting of textures from external sources (for example, hosted on user’s server). Shapespark doesn’t support uploading of images that are not part of the scene.

You can show If you would like to show an image, you could do it rather only with a custom material picker like the one in your screen shot. Texture is an object that is renderable in WebGL, it is not easy to transform such texture back to an HTML Image element and display it as a part of HTML UI. Your custom UI could keep a reference to the original HTML image, and use the original image to show the selected texture to the user.

1 Like

Hi @jan, thanks again.

I did host now the textures from external sources our own server, but I got an issue, whenever I use my custom material picker, it seems like it removes the material. like this screenshot below:

here’s our project link :

For this one

var viewer = WALK.getViewer();
viewer.onSceneReadyToDisplay(function() {
var setMaterialForNodeOriginal = viewer.setMaterialForNode;
viewer.setMaterialForNode = function(material, node) {
setMaterialForNodeOriginal.apply(this, [material, node]);
showMessage('material: ’ +;

I’ve use the and I couldnt make it appear anything, what are the methods inside material? my goal is to show the base texture name instead of the material name.

Thank you!

@Half_stack can you configure the server to return one of the following two headers with texture related responses:
Access-Control-Allow-Origin: *
Without such header browsers won’t allow the textures from your server to be used in WebGL.

1 Like

@jan I just did add the following header response on the server:


I’ve used this http checker to check if the header response is included:

this is the url for one of the texture :

and our project url :

Still it does’nt work.

Thanks @jan

It looks like CloudFlare that your server is using still returns a cached texture without this header. When I inspect the header in the Network panel of the browser debug console (F12) the header is missing and there is a cf-cache-status: HIT header that indicates that the response is served from CloudFlare cache. If I open the texture with some string added to the URL to bypass the cache, like: the header is present.

You can wait until CloudFlare cache clears, or force CloudFlare to refresh the cache.

1 Like

Tried to replace the image path with the foo=bar querystring to test the texture picker


still won’t work.

Appreciate all the help @jan

I’m sorry, the header I asked you to configure is incorrect, because the URL has to include protocol:


instead of Access-Control-Allow-Origin:

Please also add crossorigin="anonymous" property to html <img> elements. In case of your menu it will look like this:

<img class="textureSelect" targetarea="FLOOR1" roughness="img" metallic="0.2" bump="null" roughnessCode="156_roughness"
                 id="floor1_156_parquet_medium_color_texture" crossorigin="anonymous"/>
1 Like

Thank you @jan, It solved my problems for the textures.

I have 2 questions for the API
Is there a way to target this for the custom material picker.

Also I plan to create a separate button to trigger the same functionality with this arrow:
this would make our custom picker uniform with the separate button, just want to ask what function do I trigger to show and hide similar with that arrow on that screenshot.

Thank you so much