How do I apply a shader on a PackedScene?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By JulioYagami

I have a PackedScene that extends Node2D and I want to apply a shader over it. I tried using another Node2D and then I put a material shader on it, but it did not work.

:bust_in_silhouette: Reply From: MysteryGM

You can’t apply a shader to a PackedScene, instead Godot allows you to change the shader of every instance of that scene.

In other words, change the shader just before the object is added to the game:

extends Spatial

export (PackedScene) var TheScene = null
export (ShaderMaterial) var TheNewShader = null

func _ready():
	
	if TheScene != null :
		var CloneOfScene  = TheScene.instance()
		#The scene I am using is Spatial with a MeshInstance as a child
		var TheMesh = CloneOfScene.get_node("MeshInstance") as MeshInstance
		
		#Now that I have a pointer to the mesh, I can change it's material
		if TheNewShader != null :
			#Set the new material to slot 0
			TheMesh.set_surface_material(0, TheNewShader)
			
		#Lastly add the now modified instance to the game
		self.add_child(CloneOfScene)

I think it would work if I been working with 3D, but I’m currently working with 2D.

JulioYagami | 2018-12-02 18:24

2D is easier. Because sprites can only have one material, they don’t need any fancy checks.
You just use material = newMaterial

extends Node2D
    
export (PackedScene) var TheScene = null
export (ShaderMaterial) var TheNewShader = null
    
func _ready():
	if TheScene != null :
		var CloneOfScene  = TheScene.instance()
		#As a 2D scene I decided just to use a sprite, 
		#it has nothing else in the scene, if your scene
		# has some other things, you will need to find a path to it.
		if TheNewShader != null :
			#Sprites only have a one material so it is done like this
			CloneOfScene.material = TheNewShader
		#Lastly add the now modified instance to the game
		self.add_child(CloneOfScene)

MysteryGM | 2018-12-02 18:50