Jump to content

[1.9.x] Textures Unlimited - PBR-Shader, Texture Set, and Model Loading API


Shadowmage

Recommended Posts

Hmm...which one of these is recolored?

7HjDLt3.png

(also one is using the stock legacy shader, the other is using TU/Metallic)

Normalized recoloring really does allow for very precise setup of the recoloring system.  Its a bit more setup work, but the results can be very consistent between parts, and allow for the recoloring GUI to be used as intended (where the 0-255 range is all that is needed).

KAlGev9.png

Working on doing some testing and writing up documentation; release is pretty much ready pending any major bugs being found.  Hopefully will get time to pack it up tomorrow.

Link to comment
Share on other sites

If you ever want to tinker with skybox resets... I've narrowed down the issues to a few:

  1. Create a ReflectionProbe attached to the Vessel GameObject
  2. Set it to Real-Time, cullingMask = 0, and clearFlags = Skybox
    1. This will show as atmo blue by default
  3. Set the RenderSettings.Skybox to a skybox material
    1. From now on, the reflectionProbe will be completely black, no matter what you set the skybox to
    2. It seems that the clearFlags=Skybox only works for solid colors, and not for an actual Skybox material?

 

Another thing I am working on is the fact that in Unity, if you add a new Skybox component to a Camera's GameObject, the camera should use that Skybox as an override to the RenderSettings one. I've only just started playing with this, though. It also seems to be more efficient to have a camera with a RenderTexture set as target instead of doing manual RenderToCubemap, but cameras seem more difficult to mess with for reflections due to needing all 6 sides and the camera fov and other settings.

Edited by Electrocutor
Link to comment
Share on other sites

7 hours ago, Manwith Noname said:

Edit: Also, is the bloom and depth of field configurable?

I'm just using KS3P in those screenshots.  So, yes its configurable, but also a giant PITA to do so, and can only be done with file edits.

Most likely will be including at least bloom in a TU-Post Process package; will be starting work on this after all of the 1.5 update fun is finished.

13 minutes ago, Electrocutor said:

If you ever want to tinker with skybox resets... I've narrowed down the issues to a few: [...snip...]

Interesting.  Gotta love the quirks with Unity.

One thing I was going to suggest, to aid in sanity, would be to try all of this stuff from within the Unity Editor first.  Much faster edit->compile-> test timing; and I've generally found that if I can get it working in the editor, I can get it working in KSP.  Also allows to change around project settings easily (whereas in KSP you gotta use scripts to dig into the guts to get to those settings).

19 minutes ago, Electrocutor said:

Another thing I am working on is the fact that in Unity, if you add a new Skybox component to a Camera's GameObject, the camera should use that Skybox as an override to the RenderSettings one. I've only just started playing with this, though. It also seems to be more efficient to have a camera with a RenderTexture set as target instead of doing manual RenderToCubemap, but cameras seem more difficult to mess with for reflections due to needing all 6 sides and the camera fov and other settings.

Good stuff to investigate.

Yes, cameras are kind of a PITA to get render-settings correct on for cubemap capture.  But you are probably right in that it would be more efficient after the quirks are figured out.  Doing per-face manual capture would also allow to 'fix' the inverted/flipped faces found when doing capture for DX9/11.

Link to comment
Share on other sites

Development Update:

Doesn't look like the new releases will be entirely ready today.  It is all functional and working, but there are a couple of the interfaces that need to be optimized/stabilized/finalized, and it would be bad form to post a release just to break stuff in a few days with another update.  So will hold off on release until that stuff has been finished up.  You are free to use the /dev branch to give it a test drive/etc, but please don't do any serious work against the shader properties for the new shaders yet, as there may be some name-changes or texture channel remapping.  The good news is that the KSP 1.4.x versions should still work fine with KSP 1.5+ (as long as DX9 is not used), so its not like the delayed release should really be holding anyone back (except for CKAN version depenency stuff.... which isn't really my problem anyway).

I also think that I will be splitting off the current Blend-Shape / Shape-Key based model loading into its own 'mini-mod'.  It will still ship with TU by default, but will also be available as a stand-alone download for mods who only want to include that functionality and don't need any of the shader/texture stuff.  I'm doing this specifically so that the few mods out there who only use model loading won't continue to bug their users with the DX9 API warning.  Mostly I think this is mods by @bcink, but there may be a few others as well.  I'm not sure if this is going to be done for the next upcoming release, but it will be done in the very near future.

Link to comment
Share on other sites

Through my testing, I've gotten everything to work except:

oProbe.clearFlags = UnityEngine.Rendering.ReflectionProbeClearFlags.Skybox;

... when skybox is not null. Anytime skybox is not null, it fills the clear with copies of the ReflectionProbe's own internal texture on every face instead of the one that is in the skybox.

----

Adding a custom skybox to a camera works perfectly fine, but I'd prefer to use a reflectionprobe if possible since they are far more optimized.

Link to comment
Share on other sites

6 minutes ago, Electrocutor said:

Adding a custom skybox to a camera works perfectly fine, but I'd prefer to use a reflectionprobe if possible since they are far more optimized.

Not to mention that just putting a cubemap on the camera.skybox doesn't properly handle the specular convolution that is needed for proper reflection support.


Interesting findings though.  As soon as I'm done with the immediate WIP stuff for TU I'll likely dig into this again to see if I can help you find an easier method / find the quirk with the RenderSettings.skybox.

Link to comment
Share on other sites

Here is the camera RenderToCube directly put into the ReflectionProbe:

Spoiler

z7Vcnqz.jpg

Here is the camera RenderToCube put into the TU Skybox, then set the ReflectionProbe to Skybox only:

Spoiler

A3Q3QsC.jpg

I think my issues may start here. Any idea why the skybox is all messed up like that?

Link to comment
Share on other sites

3 hours ago, Electrocutor said:

I think my issues may start here. Any idea why the skybox is all messed up like that?

I can't particularly think of any....  I don't suppose you've put together a way to dump those cubemaps to disk?  Analyzing the per-face .pngs was how I figured out much of TU's issues.

Hmm...let me see if I can duplicate the issue in the Unity Editor sometime today... lots easier to test stuff there.

Have you tried making sure the SkyBox is set using a std CubeMap rather than a RenderTexture?  Might be something going on where the reflection probe is somehow re-using the skybox' texture for its internal rendering/processing.  Really shouldn't happen....but I can't really think of any other reason.

Link to comment
Share on other sites

Initial testing reveals that this all appears to work fine in the editor:

Create a new scene.  Add a reflprobe set to 'realtime-every frame', 'capture everything', clear mode of skybox.  Add a few random objects, and a camera to use for cubemap gen.  Script creates a new renderTexture during startup, uses this for skybox shader/material directly.

Enable camera, run script to gen cubemap, place cubmap into material, set material to skybox.  Reflection probe now captures the new skybox, without artifacts.

 

Hmm... okay.. well.. it works until I try and -move- anything.  And then it reveals at least one issue -- the cubemap used for skybox generation needs to be 'cleared' every frame, or it will still contain the previous frames' data.

Going to try and get a simplified test-case working within KSP, in the absence of any other TU related reflection handling.

 

Link to comment
Share on other sites

I got it working: I switched to the Hidden/CubeCopy shader for the skybox and set farClip to 5000f it all works fine now. Unfortunately, I seem to be having some sort of saturation issue or something:

uZL0THN.jpg

You can barely make out the VAB as the skybox is blending with it or has normalized the real-time render or something... if I don't set the skybox, it renders perfectly fine, so I am still missing something.

My understanding is that the skybox gets put in the color buffer and then the real-time probe renders into the depth buffer before overwriting, is that not correct?

Edited by Electrocutor
Link to comment
Share on other sites

4 minutes ago, Electrocutor said:

You can barely make out the VAB as the skybox is blending with it or has normalized the real-time render or something

I'm guessing that is an artifact of the shader you are using... it is really not intended for standard rendering. (what was the previous shader you were using?)

Let me do some tests today/this week with some known-to-work shaders, and will let you know what I come up with.

Link to comment
Share on other sites

2 minutes ago, Shadowmage said:

I'm guessing that is an artifact of the shader you are using... it is really not intended for standard rendering. (what was the previous shader you were using?)

Let me do some tests today/this week with some known-to-work shaders, and will let you know what I come up with.

I was using the TU Skybox shader, but if I had to guess it doesn't work for this because it is fickle about the x,y,z rotation of the cubemap when setting it, whereas the CubeCopy is just a straight WYSIWYG.

Link to comment
Share on other sites

5 minutes ago, Electrocutor said:

I was using the TU Skybox shader,

Interesting.  Can verify that that shader does not work properly in the same scene I was trying earlier (whereas the Unity Skybox/Cubemap shader does work).  Likely some culling/clearing/etc stuff that I've not set properly in my skybox shader....

Let me see if I can bundle up a shader for you that might work (if you are interested?).  (Now that I have an in Editor test case that I can use for debug, should be easily solvable)

 

Edited by Shadowmage
Link to comment
Share on other sites

15 minutes ago, Electrocutor said:

I am interested, but mostly to find a super efficient way of doing it right. After the near and far scenery is done, I am going to work on layer0 to get Kerbals and Vessels showing up and reflecting each other in windows and such.

https://www.dropbox.com/s/6858nxhnps6yvgy/TU-SkyboxShader.ssf?dl=0

Tested to work properly in Unity Editor.  Looks like the issue I had was that I was culling front faces; the Unity version does no culling.  Also added HDR support and _Exposure parameter... just for giggles.

You'll need to use whatever asset-bundle loader you were using to load the other TU shader packs.  There is only a single shader in the above linked pack -- TU/Skybox

(please let me know if this works better/at all)

Link to comment
Share on other sites

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace UnofficialPatch
{
    public class FixReflections
    {
        private EventData<GameEvents.HostedFromToAction<Vessel, Vessel.Situations>>.OnEvent VesselSituationChangedEvent;
        private Shader _TUSkyboxShader;

        public void Start()
        {
            this.VesselSituationChangedEvent = new EventData<GameEvents.HostedFromToAction<Vessel, Vessel.Situations>>.OnEvent(VesselSituationChangedEventHandler);
            GameEvents.onVesselSituationChange.Add(this.VesselSituationChangedEvent);

            Shader[] aryShaders = Resources.FindObjectsOfTypeAll<Shader>();
            foreach (Shader oShader in aryShaders)
            {
                if (oShader.name == "SSTU/Skybox/Cubemap")
                {
                    _TUSkyboxShader = oShader;
                    break;
                }
            }

            //SceneManager.activeSceneChanged += SceneManager_activeSceneChanged;
        }

        private void SceneManager_activeSceneChanged(Scene arg0, Scene arg1)
        {
            Debug.Log("Scene: '" + arg1.name);
            Debug.Log("AmbientMode: " + RenderSettings.ambientMode.ToString());
            Debug.Log("ReflectionMode: " + RenderSettings.defaultReflectionMode.ToString());
            Debug.Log("Skybox: " + (RenderSettings.skybox == null ? "null" : RenderSettings.skybox.name));
            Debug.Log("CustomReflection: " + (RenderSettings.customReflection == null ? "null" : "cubemap"));
        }

        private void VesselSituationChangedEventHandler(GameEvents.HostedFromToAction<Vessel, Vessel.Situations> oSituation)
        {
            if (oSituation.host == null || !oSituation.host.isActiveVessel)
            { return; }

            UpdateReflections(oSituation.host, oSituation.to);

            //Debug.Log("[UnofficialPatch] Vessel SituationChanged: " + oSituation.host.name + " - " + oSituation.to.ToString());
        }

        private void UpdateReflections(Vessel oVessel, Vessel.Situations oSituation)
        {
            Transform oTransform;
            GameObject oFarReflect;
            GameObject oNearReflect;
            Camera oCamera;
            ReflectionProbe oProbe;
            Skybox oSkybox;
            Cubemap oSkyboxCube;
            List<KSPLayer> oLayers = new List<KSPLayer>();

            oTransform = oVessel.gameObject.transform.Find("FarReflect");
            if (oTransform == null)
            {
                oFarReflect = new GameObject("FarReflect");
                oFarReflect.transform.SetParent(oVessel.gameObject.transform, false);

                oCamera = oFarReflect.AddComponent<Camera>();
                oCamera.enabled = false;
                oCamera.clearFlags = CameraClearFlags.SolidColor;
            }
            else
            {
                oFarReflect = oTransform.gameObject;
                oCamera = oFarReflect.GetComponent<Camera>();
            }

            oTransform = oVessel.gameObject.transform.Find("NearReflect");
            if (oTransform == null)
            {
                oNearReflect = new GameObject("NearReflect");
                oNearReflect.transform.SetParent(oVessel.gameObject.transform, false);

                oSkybox = oNearReflect.AddComponent<Skybox>();
                oSkybox.material = new Material(Shader.Find("Hidden/CubeCopy"));
                oSkyboxCube = new Cubemap(512, TextureFormat.RGBA32, false);
                oSkybox.material.mainTexture = oSkyboxCube;

                oProbe = oNearReflect.AddComponent<ReflectionProbe>();
                oProbe.mode = UnityEngine.Rendering.ReflectionProbeMode.Realtime;
                oProbe.refreshMode = UnityEngine.Rendering.ReflectionProbeRefreshMode.EveryFrame;
                oProbe.timeSlicingMode = UnityEngine.Rendering.ReflectionProbeTimeSlicingMode.IndividualFaces;
                oProbe.clearFlags = UnityEngine.Rendering.ReflectionProbeClearFlags.Skybox;
                oProbe.farClipPlane = 100000f;
            }
            else
            {
                oNearReflect = oTransform.gameObject;
                oProbe = oNearReflect.GetComponent<ReflectionProbe>();
                oSkybox = oNearReflect.GetComponent<Skybox>();
                oSkyboxCube = (Cubemap)oSkybox.material.mainTexture;
            }

            if (oSituation == Vessel.Situations.PRELAUNCH || oSituation == Vessel.Situations.LANDED || oSituation == Vessel.Situations.SPLASHED || (oSituation == Vessel.Situations.FLYING && oVessel.altitude < 10000))
            {
                oLayers.Add(KSPLayer.Atmosphere);
                //oLayers.Add(KSPLayer.ScaledScenery);
                oCamera.cullingMask = GetCullingMask(oLayers);
                oCamera.backgroundColor = RenderSettings.ambientSkyColor;

                oLayers.Clear();
                oLayers.Add(KSPLayer.LocalScenery);
                oLayers.Add(KSPLayer.Water);
                oProbe.cullingMask = GetCullingMask(oLayers);
            }
            else
            {
                oLayers.Add(KSPLayer.SkySphere);
                oCamera.cullingMask = GetCullingMask(oLayers);
                oCamera.backgroundColor = Color.black;
                RenderSettings.ambientSkyColor = Color.black;

                oLayers.Clear();
                oLayers.Add(KSPLayer.Atmosphere);
                oLayers.Add(KSPLayer.ScaledScenery);
                oProbe.cullingMask = GetCullingMask(oLayers);
            }

            oCamera.RenderToCubemap(oSkyboxCube);
            RenderSettings.skybox = oSkybox.material;
        }

        public static int GetCullingMask(List<KSPLayer> oLayers)
        {
            int iCullingMask = 0;

            foreach (KSPLayer oLayer in oLayers)
            { iCullingMask = (iCullingMask | (1 << (int)oLayer)); }

            return iCullingMask;
        }

        public enum KSPLayer
        {
            Default = 0,
            TransparentFX = 1,
            IgnoreRaycast = 2,

            Water = 4,
            UI = 5,


            PartsList_Icons = 8,
            Atmosphere = 9,
            ScaledScenery = 10,
            UI_Dialog = 11,
            UI_Vectors = 12,
            UI_Mask = 13,
            Screens = 14,
            LocalScenery = 15,
            Unknown = 16,
            EVA = 17,
            SkySphere = 18,
            PhysicalObjects = 19,
            InternalSpace = 20,
            PartTriggers = 21,
            KerbalInstructors = 22,
            AeroFxIgnore = 23,
            MapFX = 24,
            UI_Additional = 25,
            WheelCollidersIgnore = 26,
            WheelColliders = 27,
            TerrainColliders = 28,
            DragRender = 29,
            SurfaceFx = 30,
            Vectors = 31
        }
    }
}

 

Edited by Electrocutor
Link to comment
Share on other sites

46 minutes ago, Electrocutor said:

My understanding is that the skybox gets put in the color buffer and then the real-time probe renders into the depth buffer before overwriting, is that not correct?

IDK, that is more technical details than I was ever able to find out on how Reflection Probes function internally.  Seems logical though from what I know of the GFX pipeline -- blit the color buffer from the skybox texture into the color buffer of the reflection probe, and then capture the scenery while rendering on top of that background image.

Link to comment
Share on other sites

2 hours ago, Electrocutor said:

I got it working: I switched to the Hidden/CubeCopy shader for the skybox and set farClip to 5000f it all works fine now. Unfortunately, I seem to be having some sort of saturation issue or something:

uZL0THN.jpg

You can barely make out the VAB as the skybox is blending with it or has normalized the real-time render or something... if I don't set the skybox, it renders perfectly fine, so I am still missing something.

My understanding is that the skybox gets put in the color buffer and then the real-time probe renders into the depth buffer before overwriting, is that not correct?

So... the precise thing you are seeing there is being caused by the atmosphere rendering ON TOP OF the scenery layer.  You have to split those into different render passes.  This is because the 'atmoshphere' is physically closer to the camera than the scenery (you know.. SQUAD could have fixed all of their rendering problems with proper rendering and shader setups? -- render the atmo as a skybox itself, in the 'background' pass...  too late now...).

Here I am using a debug-sphere to render the texture that will be used by the skybox.  I first set it to render atmosphere... no problems there.  But when I tell it to also render 'scenery' in that same pass... you get the mess seen in the images:

UPv1Oct.png

I have reflections turned off in this setup, hence the black part textures -- so far I'm just getting the 'skybox' rendering to work before working on any of the probe stuff.

However... your concept appears to work when it is composited correctly (using the TU/Skybox shader I provided earlier).  Here is an image using the RenderSettings.skybox to hold a cubemap of the KSP galaxy, atmo, and scaled-space layers, with the reflection probe set to 'use skybox' and only capture 'scenery' layers.  This is with the debug-sphere configured with a standard material, set to full metallic and full specular -- so what you are seeing is the results of the render probe.

9qtCaEZ.png

 

So...concept works fine.  Might be faster than what is currently used in TU, depending on precisely how each pass/layer is captured.  Just need to figure out the layering setup/etc.  Code for the above example can be found here:  https://github.com/shadowmage45/TexturesUnlimited/blob/dev/Plugin/SSTUTools/KSPShaderTools/Addon/ReflectionManager2.cs

(note that I butchered the dev branch to do this... so the normal reflection stuff has been disabled in /dev until I'm done with these tests)

(tested on KSP 1.4.3, using OpenGL-Core)

Edit:  Full setup for 'working' scene:

RelfectionCamera with near/far of   0.01f / 3.0e7f;  layer mask set to capture galaxy, atmo, scaled space;  clear flags set to 'Solid Color'.  Renders to a RenderTexture, ARGB32, 24-bit, set as cubemap.
Skybox material uses 'TU/Skybox' shader.
RenderSettings.Skybox set every frame to use the output from skybox capture camera.
RenderProbe with default near/far; layer mask set to capture scenery only; clear flags set to 'skybox'.

Edited by Shadowmage
Link to comment
Share on other sites

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...