renight0 It's in Render Target section in the Inspector.

@xyz If it is the sub-menu under the render target for the SubViewport Node it already set like this (and won't work as I want)

  • xyz replied to this.

    renight0 You have no lights in the scene so all pixels end up being fully black which results in final value of 0.0

      xyz That's because I'm instancing this LightDetect packed scene into my Character scene, and the character packed scene is being instanced in my testLevel scene. So I was expecting it would create images using the testLevel scene light.

      • xyz replied to this.

        renight0 If you run it in testLevel it won't give all zeros. Test it out by printing the entire array from the function that creates it.

          xyz I am running it on my testLevel scene. And lightValue gets equals to zero and the floats array is [0,0,0,....]. I put a print(lightValue) line and also inserted a breakpoint to debug and see each variable value. Those are the values I get

          • xyz replied to this.

            renight0 You need to manually update global position of Camera3D that's parented to SubViewport, every frame. Best to do it in _process() in LightDetect.gd. It won't automatically inherit any 3D transforms from ancestor nodes because 3D transformation chain is broken by inserting non-3D nodes (SubViewport and SubViewportContainer) inbetween.

            Alternatively you can use RemoteTransform3D node to drive camera's position.

              xyz I tried both ways. I'm not sure I did it correctly. First I tried the RemoteTransform3D node (didn't know this node before) (How do I highlight these names?). I set the Remote Path to the Light Detect (Node 3D parent) and it did not work.

              Then I tried the following code on _process() in LightDetect.gd and also got the same result.

              
              extends Node3D
              
              var LightLevel : float
              
              @onready var camera_3d: Camera3D = $SubViewportContainer/SubViewport/Camera3D
              @onready var light_detect: Node3D = $"."
              
              func _process(delta: float) -> void:
              	
              	# The following code will take a screenshot of our camera and create an array of floats
              	# that will be used to average the float values so we can determine our general lightness
              	# values. Obs: An image is like an array of pixels
              	#var image : Image = get_node("SubViewportContainer/SubViewport").get_texture().get_image()
              	
              	camera_3d.global_position = light_detect.global_position + Vector3(0,1.3,0)
              	
              	var LightDetectSV : SubViewport = get_tree().get_nodes_in_group("LightDetectSubViewport")[0]
              	
              	var image : Image = LightDetectSV.get_texture().get_image()
              	
              	var floats : Array[float]
              	
              	for y in range(0, image.get_height()):
              		for x in range (0, image.get_width()):
              			var pixel = image.get_pixel(x,y)
              			var lightValue = (pixel.r + pixel.g + pixel.b) / 3
              			floats.append(lightValue)
              	return average(floats)
              	pass
              
              func average(numbers: Array[float]) :
              	var sum = 0.0
              	for n in numbers:
              		sum += n
              	return sum / numbers.size()
              • xyz replied to this.

                renight0 it did not work

                In what way it didn't work?

                Also why do you return something from _process() whose return value is declared void?

                  xyz

                  xyz In what way it didn't work?

                  The lightValue is always zero and the floats array is always [0,0,0,...0]. There values should be in a 0 to 1 interval.

                  xyz Also why do you return something from _process() whose return value is declared void?

                  I should probably have made the floats array a "public" global variable instead of trying to return something. It needs to be read by other scripts.

                  • xyz replied to this.

                    renight0 Instead of return average(float) put print(floats) and run the main scene. What gets printed?

                      xyz Now it worked!
                      I had been missing 2 thing:

                      1. I completely forgot to assign LightLevel = average(floats)

                      2. At some point I hid the LightDetect scene nodes i-i

                      Thanks for pointing out I needed to move the camera LightDetect scene camera by code. I had no idea. I just checked and you're completely right.