Jump to content

Render Texture Camera and KSP, Culling, Layers, Masks?


Recommended Posts

I'm trying to write a small part module to take a "Snapshot" of the scene using a transform on a part, and save that snapshot to a PNG file. in effect a simple low-res camera.

I've thankfully got things half working, a little camera part:

pNGcYqV.jpg

But the problems are with what the render is actually producing, examples:

oMlg3mo.jpg

So you might notice there, only certain objects are showing up in the render, but they are missing skybox, terrain, etc.

I believe (though might be wrong) this is down to culling, layer, etc. settings on the camera, but really scratching my head to get the correct setup.

Right now using cullingMask settings from the Wiki but might be out of date:

 camera = cameraGameObject.AddComponent<Camera>();
            camera.cullingMask = 8685073; // Specifically for EVA view.
            camera.clearFlags = CameraClearFlags.Nothing;

            camera.fieldOfView = cameraFieldOfView;
            camera.enabled = false;

That produces the images above with transparent BG, only showing space centre objects.

You might notice two screenshots where you can see the "global ocean" that sits under the surface mesh, this was displayed when I set the mask to 63 specifically.

So  I guess, which mask to use exactly? Or is something else causing this?
Any help is really really appreciated, scratching my head crazy to this.

@JPLRepo Hate to ping, but your work on Tarsier seemed very relevant, unfortunately digging through the sourcecode I wasn't able to find anything exactly specific to this, anything you know in this area?
Thanks :)

Here's the entire script (Note: saving to C:\output\ is a temporary measure):


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using System.IO;

namespace TantaresUM
{
    public class ModuleTantaresCamera : PartModule
    {
        [KSPField]
        public string cameraTransformName = "cameraTransform";

        [KSPField]
        public float cameraFieldOfView = 60;

        [KSPField]
        public int cameraHorizontalResolution = 128;

        [KSPField]
        public int cameraVerticalResolution = 128;

        private GameObject cameraGameObject = null;
        private Camera camera = null;

        const string DEBUG_LOG_PREFIX = "ModuleTantaresCamera";

        public void Start()
        {
            cameraGameObject = base.gameObject.GetChild(cameraTransformName);

            if (cameraGameObject == null)
            {
                Debug.LogFormat("[{0}] Camera game object is missing.",DEBUG_LOG_PREFIX);
                return;
            }

            

            camera = cameraGameObject.AddComponent<Camera>();
            camera.cullingMask = 8685073; // Specifically for EVA view.
            camera.clearFlags = CameraClearFlags.Nothing;
            
            //camera.aspect = 1f;
            //camera.farClipPlane = 3000f;
            camera.fieldOfView = cameraFieldOfView;
            camera.enabled = false;
        }

        [KSPAction(guiName = "Capture Image", activeEditor = true)]
        public void ActionCaptureImage(KSPActionParam param)
        {
            CaptureImage();
        }

        [KSPEvent(guiActive = true, guiActiveEditor = true, guiName = "Capture Image", active = true)]
        public void EventCaptureImage()
        {
            CaptureImage();
        }

        public void CaptureImage()
        {  
            try
            {

                // Switch the camera on.

                Debug.LogFormat("[{0}] Switching camera on.", DEBUG_LOG_PREFIX);

                camera.enabled = true;

                // Render camera to texture.

                Debug.LogFormat("[{0}] Setting up the render textures.", DEBUG_LOG_PREFIX);

                RenderTexture renderTexture = new RenderTexture(cameraHorizontalResolution, cameraVerticalResolution, 24);
                var imageTexture = new Texture2D(cameraHorizontalResolution, cameraVerticalResolution);

                camera.targetTexture = renderTexture;
                
                camera.Render();
                RenderTexture.active = renderTexture;
                
                imageTexture.ReadPixels(new Rect(0, 0, camera.targetTexture.width, camera.targetTexture.height), 0, 0);
                imageTexture.Apply();
                

                Debug.LogFormat("[{0}] Encoding render texture to bytes.", DEBUG_LOG_PREFIX);

                byte[] bytes = imageTexture.EncodeToPNG();
                Destroy(imageTexture);

                // Disable the render texture.

                Debug.LogFormat("[{0}] Cleaning up render textures.", DEBUG_LOG_PREFIX);

                RenderTexture.active = null;
                camera.targetTexture = null;

                // Switch the camera off.

                Debug.LogFormat("[{0}] Switching camera off.", DEBUG_LOG_PREFIX);

                camera.enabled = false;

                // Write the file.

                string fileName = string.Format(@"C:\output\image{0}.png", Guid.NewGuid().ToString());

                File.WriteAllBytes(fileName, bytes);
            }
            catch(Exception ex)
            {
                Debug.LogFormat("[{0}] Error capturing image.", DEBUG_LOG_PREFIX);
                Debug.LogFormat("[{0}] {1}.", DEBUG_LOG_PREFIX, ex.Message);
            }
            
            
        }
    }
}

 

Link to comment
Share on other sites

Yep. You have to render all layers. You are only rendering some.
You also can't render them all using one camera, because you need to render the layers in the same order as the game. with different ordered cameras.

The way TST mod does it is it creates it's own cameras copying from each of the KSP cameras and then renders them in the same order as KSP does onto a rendertexture.

The cameras are:
galaxy camera.
Scaled space camera.
Camera01 - this one only operates in OpenGL not DX11 so you need to check for that and only enable/use this one if the game is running in OpenGL.
Camera00

TST just makes it's own copy of each of these cameras. Unity Camera class has a CopyFrom function that will copy all the settings of the camera to another instance.

 

 

Link to comment
Share on other sites

6 hours ago, JPLRepo said:

Yep. You have to render all layers. You are only rendering some.
You also can't render them all using one camera, because you need to render the layers in the same order as the game. with different ordered cameras.

The way TST mod does it is it creates it's own cameras copying from each of the KSP cameras and then renders them in the same order as KSP does onto a rendertexture.

The cameras are:
galaxy camera.
Scaled space camera.
Camera01 - this one only operates in OpenGL not DX11 so you need to check for that and only enable/use this one if the game is running in OpenGL.
Camera00

TST just makes it's own copy of each of these cameras. Unity Camera class has a CopyFrom function that will copy all the settings of the camera to another instance.

 

 

Appreciate it!

With a (lot) bit of help, it's working :)

Many thanks.

image_c6334eab-2d53-41bc-8ed0-75a086b11b

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...