Change model texture in runtime?

Can i change a texture of model in runtime?

Yes i can. https://www.defold.com/ref/model/#texture0
But i need to add images to custom resources.
Texture looks broken, but i can changed it=)

local texture = resource.load("/assets/img/logo.png")
local wall = factory.create("#factory", wall_pos)
local url = msg.url(wall)
url.fragment = "model"
			   
local resource_path = go.get(url, "texture0")
local header = { width=128, height=128, type=resource.TEXTURE_TYPE_2D, format=resource.TEXTURE_FORMAT_RGBA, num_mip_maps=1 }
 resource.set_texture(resource_path, header, texture)

How does it look broken? Is the image same size?

1 Like

I try to load a texture with path from model, but it is not working.

local texture2 = resource.load("/build/default/assets/img/wall.texturec")

I try same size texture, same problem

Upload a stripped down version of the project as a zip with examples of the problems.

1 Like

I push all project in github
Script that changing model in pseudo/go/wall_factory/wall_factory_script . I try change texture to the same texture but it is not help

I’m doing some tests now. Did you already try something like

local map = require ("pseudo.modules.map")


function on_message(self, message_id, message, sender)
	local delta_x=1
	local delta_z=1
	local wall_pos= vmath.vector3(0)
	
	local texture = resource.load("/assets/img/wall.png")
	
	for y=1,map.get_height() do
		for x=1,map.get_width() do
			if(map.is_blocking(x,y)) then 
    	  	wall_pos.x = (x-1) * delta_x + 0.5
    	  	wall_pos.z = -(y-1) * delta_z - 0.5    
            --  print(wall_pos)
    	  	
				local wall = factory.create("#factory", wall_pos)
				local url = msg.url(wall)
				url.fragment = "model"
			   
			   local buffer = resource.load("/assets/img/wall.texturec")
			   resource.set(go.get(url, "texture0"), buffer)

			   
             end
      end
  end
end

To get Defold to make the texturec versions of sprites you have to define them in a model once though, could have a GO with a bunch of models and sprites attached to force it maybe… I got it to load a color shifted texture with this method

You also want the samplers of the wall material to be nearest for pixel art textures?

3 Likes

Thx, I will try texturec.

Yes

Another hack with texturec may be to make a build with a bunch defined on models once, then grab them from the build folder, copy them into a data folder in the game project, then define the folder the pre-made texturec files are in as custom resource. Have not tested so this may not work but if it does may be better than having a bunch of models with textures defined to force creation of texturec files.

1 Like

I create all my model in factory. But when i changed texture for one model, it is changed for all models. :thinking: Can someone explain why?

local delta_x=1
	local delta_z=1
	local wall_pos= vmath.vector3(0)
	
	local textures = {resource.load("/assets/img/texture/wall1.texturec")
	,resource.load("/assets/img/texture/wall2.texturec")
	,resource.load("/assets/img/texture/wall3.texturec")
	,resource.load("/assets/img/texture/wall4.texturec")}
	
	for y=1,map.get_height() do
		for x=1,map.get_width() do
			if(map.is_blocking(x,y)) then 
    	  	            wall_pos.x = (x-1) * delta_x + 0.5
    	  	            wall_pos.z = -(y-1) * delta_z - 0.5    
    	  	
			    local wall = factory.create("#factory", wall_pos)
			    local url = msg.url(wall)
			    url.fragment = "model"
			    local resource_path = go.get(url, "texture0")
			    print("texture_id:"..map.get_cell(x,y).texture)
			   resource.set(resource_path, textures[map.get_cell(x,y).texture])   
                        end
                 end
           end

All model will have texture 3 .Logs:

...
DEBUG:SCRIPT: texture_id:1
DEBUG:SCRIPT: texture_id:3

I think that i understand what happened. :slight_smile:
Model has a read only property texture0. So i can’t change model texture.I am changing a texture.

First I get a path to texture.
Then i load a new texture in memory.
Then i changed old texture to new texture.

local resource_path = go.get(model_url, "texture0")
local texture = resource.load("/assets/img/texture/wall1.texturec")
resource.set(resource_path, textures[map.get_cell(x,y).texture]

So looks like i can’t changed a texture for model.

In my game i have walls. The idea was to have only one go and factory for all type of walls. But looks like the only way, is to have a go for every type of wall, and a factory for every go. :frowning_face:

1 Like

Why texture for model read only?

Well, if you think about it it makes perfect sense. If you have multiple sprites or models (or anything else with a graphical representation) using the same texture it will be exactly the same texture (ie the same allocated memory holding the image) for every instance of the component. If every sprite or model would have its own texture then you’d very quickly run out of memory. This means that if you change the texture it will affect every component that references that texture.

2 Likes

The idea was to load a textures once, for example in init. Then changed reference in model, to texture that i need.

The equivalent of this is to make a separate GO and factory for each one, so the engine will load it for you. Though I know it can be a bit tedious to duplicate things if you have a lot of different versions. It’s the same deal with sounds, collision, etc.

1 Like

That not very big problem, i can have factories and go. I try changing texture because, i want to draw sprites like in wolfenstein 3d: 2d image in 3d world, always looking at player.

For now i done them like a plane model. The problem that i can have a lot of different sprites.

I try to draw sprites in 3d, but i don’t see them.

1 Like

Newermind i fixed sprite, so i can use them in 3d world. I was forgot to add part of angle to sprite =) Now all work. :+1:

1 Like

One more question, why models don’t use texture atlas?

1 Like

This is actually a big problem for us as well as we want to be able to work with “skins” on our characters/models. Switching textures runtime is a must.
Now the only solution I can find in this right now is to actually have all skins on the same “bigger” texture image and in the shader change the tex_coords according to this bigger “indexed” image.

Any other solution to this problem?

7 Likes