Thomas P.

[1.7.3-2 + Backports] Kopernicus & KittopiaTech

Recommended Posts

Hey @Thomas P., whenever I load up my planet mod, I get this error where my brain comes up with this:

 

[7.12.17-LOG]

On the 12th day of Christmas, Thomas sent to me:

{
   - 12 bug reports
   - 11 strange textures
   - 10 gigs of ram
   - 9 MM patches
   - 8 broken logs
   - 7 mod suggestions
   - 6 PQS mods
   - - Fiiiive bug fixeeees
   - 4 common bugs
   - 3 push errors
   - 2 double doubles™
}

And not one plaaanet wooorked foooor meeeeeee!

Edited by Gameslinx

Share this post


Link to post
Share on other sites

I was working on some of the rings for my mod Evolution and, to ensure I had everything named right, looked up the RingLoder in Kopernicus' source code. After that I, out of curiosity, looked up the code of the ring shader, and came across the notes regarding up-close noise.

I wonder if that fade would be possible through some of the layer sorting modes used in programs such as Photoshop. Out of curiosity I decided to load up a ring texture of mine in GIMP, rendering a procedural noise, then using different layer sorting modes to see which ones yielded the best results without destroying the quality of the ring texture.

I would present screenshots here were it not for the fact that Imgur is giving me an 'SSL_ERROR_BAD_CERT_ALERT' error at the moment, so that's bloody brilliant. :/

Anyhow, back to my point. I have found that the best-looking results were the layer sorting modes 'Dodge', 'Soft Light' and 'Overlay'.

For these, the maths are as follows:

Dodge: E = (256*I) / ((255-M) + 1)

In which E is the resulting pixel color, I is the pixel color of the original image, and M is the pixel color of the noise we are applying on top.

 

Soft Light: E = (((255-I) * M + Rs)/255) * I

In which E is the resulting pixel color, I is the pixel color of the original image, and M is the pixel color of the noise we are applying on top. Note the Rs factor, which is computed through:

Rs = 255 - (((255-M)*(255-I))/255)

 

And lastly Overlay: E = (I/255) * (I+(2M/255)*(255-I))

In which E is the resulting pixel color, I is the pixel color of the original image, and M is the pixel color of the noise we are applying on top.

 

(Note: these are the equations GIMP uses for layer sorting. Therefore, because image editors use a 0-255 color range and Unity uses a 0-1 color range, adjustments to the equations will be necessary for them to work correctly in Unity.)

 

I will be testing these sorting modes further and, should they work, will try adding the best one to the ring shader (after thorough testing for glitches and memory problems before submitting a pull request of course). Here's hoping we will soon have the best ring detail, even from up-close.

Don't expect this to be possible though:

wall-e-2008-movie-review-cosmic-dust-sat

Share this post


Link to post
Share on other sites

I want to get this mod, but the 1.3 version, where do I get it?

Share this post


Link to post
Share on other sites

thanks, but I just found an old mod in one of my folders that had the 1.3 kopernicus in it. So thanks anyway.

Share this post


Link to post
Share on other sites
35 minutes ago, rockets-don't-make-toast said:

thanks, but I just found an old mod in one of my folders that had the 1.3 kopernicus in it. So thanks anyway.

Just be sure that the Kopernicus version number matches the KSP version number.  For instance, if you're using KSP 1.3.1 then you must use one of the 1.3.1-x Kopernicus versions.  It won't work if the version numbers don't match.

Share this post


Link to post
Share on other sites
3 hours ago, OhioBob said:

Just be sure that the Kopernicus version number matches the KSP version number.  For instance, if you're using KSP 1.3.1 then you must use one of the 1.3.1-x Kopernicus versions.  It won't work if the version numbers don't match.

Generally, 1.3.0 addons work in 1.3.1, and vice-versa. 

Share this post


Link to post
Share on other sites
4 minutes ago, dundun92 said:

Generally, 1.3.0 addons work in 1.3.1, and vice-versa. 

Although that may be generally true for most mods, Kopernicus is version locked.  It simply will not work if the versions don't match.  This is by design.

Share this post


Link to post
Share on other sites
17 minutes ago, dundun92 said:

Generally, 1.3.0 addons work in 1.3.1, and vice-versa. 

Kopernicus is hardcoded to be version locked, meaning Kopernicus 1.3.0-x will not work in 1.3.1-x and vice versa. 

Edited by Galileo

Share this post


Link to post
Share on other sites
5 hours ago, OhioBob said:

Although that may be generally true for most mods, Kopernicus is version locked.  It simply will not work if the versions don't match.  This is by design.

 

5 hours ago, Galileo said:

Kopernicus is hardcoded to be version locked, meaning Kopernicus 1.3.0-x will not work in 1.3.1-x and vice versa. 

Ah, I see.

 

Share this post


Link to post
Share on other sites

I've done some further testing with shaders. For this I tried downloading the ring shader Kopernicus uses from GitHub and making changes for testing purposes on a local copy, but Unity does not approve. Thus I decided to write a simple shader using the Blinn-Phong lighting model. After all, all I'm trying to do is fading textures, which doesn't require anything fancy.

I imported Cyran's ring texture as well as a dust texture I made in GIMP in a minute, and fed them to the shader.

I found two promising results:

anwE1RB.png

This was done through a 'lighten only' algorithm, where the dust map is only added if the pixel on the dust map is lighter than that of the ring texture. Because we're dealing with white dots on a black background, this yields a result similar to basic ring dust.

cB2P6fq.png

This one is even simpler. The function for this is:

E = R+D

Where E is resulting color, R is ring tex color, and D is dust color. Because the dust has a black background, the addition does nothing there, but this isn't the same fo the dust particles themselves.

Granted, this is a very basic approach and doesn't have any fancy distance-fading, but it's a start.

Share this post


Link to post
Share on other sites

Update to my previous post:

- The shader now has TWO dust 'detail' textures, so users can make both large and small particles applied on top.

- The shader now has a 'ring' detail texture besides the dust textures, ergo, from up-close rings appear subdivided into several smaller rings

- The shader now fades based on distance.

The math behind the shader is as follows:

Spoiler

There are four textures:
- _MainTex, the main ring texture
- _DustSmall, the 'small' dust texture
- _DustLarge, the 'large' dust texture
- _RingDetail, the ring detail texture (small ring subdivision)

Firstly, the main texture and ring detail are blended with the hard light mode, resulting in texture S (subdivided ring). Note that only the RED channel of the ring detail is entered into this blend.
Next, the two dust textures are added on top of each other, and merged with S using the equation: E = Max(S, D)

(Where E is resulting pixel color, S is the subdivided ring texture, and D is the sum of the two dust textures)

Next, E is entered as the second value of a Lerp function, with the first value being the original ring texture.

The factor t of this lerp function depends on distance to the ring. Therefore, if the camera gets close enough to the rings, the shader will slowly fade to the 'detailed' version.

The result of this lerp is the color output of the shader.

Next, the alpha of the main ring texture is multiplied by the GREEN channel of the ring detail, resulting in MA (multiplied alpha). This is entered into a Lerp function as the second vaule, with the first value being the alpha of the original ring texture. Again, factor t of the lerp depends on the distance between camera and surface.

 

The distance between camera and vertex (the factor t for the lerps)  is computed through:

detailDistance / Vector3.distance(vertex.position, camera.position)

 

detailDistance is the max distance that a vertex can be from the camera for detail to be added in. Ergo, if the camera is further away, detail is not rendered.

However, to avoid colors from exploding, the result of the above function is clamped between 0 and 1 before it is fed to the lerp functions.

I'm now going to try to merge it with the Kopernicus ring shader. The biggest problem will likely be the way how Kopernicus wraps ring textures.

I'll be posting a few images showing my shader in action later.

Edited by The White Guardian

Share this post


Link to post
Share on other sites

Some images of the ring detail in action.

Left: my detail shader; right: Unity built-in Standard shader

Wh2yLeK.png

Note that this is without distance filtering.

Here is a closeup comparison:

Spoiler

Unity:

RxK04GO.png

Custom shader:

tjLCH52.png

And here is a demonstration of the distance value. Because yes, the maximum detail distance can be changed easily.

 

From up-close:

Spoiler

Max distance 0

qBU05IV.png

Max distance 1

uMqxpd0.png

Max distance 2

HBxnzA1.png

Max distance 5

6pTiIZ4.png

From afar:

Spoiler

Max distance 0

Cad063e.png

Max distance 5

Z46dRsd.png

Max distance 25

q0BX27l.png

 

Share this post


Link to post
Share on other sites

I think I've merged the shaders. Have yet to compile everything to try it out though.

Because I am by far not a shader expert, I'll summarize the changes I made to a local copy, therefore if anyone spots an error, please let me know.

 

Firstly, I added a few lines to the start, after '#define M_PI'

uniform sampler2D _DustLarge; //The large dust texture
uniform sampler2D _DustSmall; //The small dust texture
uniform sampler2D _RingDetail; //The ring detail texture
uniform float _MaxDistance; //The maximum distance

A few sampler2D's for the dust and detail textures, and a float that will control the maximum detail distance.

 

Currently the ring shader used by Kopernicus looks up the color of the main texture and stores it in a Vector4, 'color', then works some shadow and scattering magic on it.

I have added a few lines before this effect magic however.

float4 _RingDetail_var = tex2D(_RingDetail, i.texCoord);
float4 _DustLarge_var = tex2D(_DustLarge, i.texCoord);
float4 _DustSmall_var = tex2D(_DustSmall, i.texCoord);

//Get the distance between ring and camera
//Saturate = clamp  between 0 and 1
//Divide MaxDistance by Vector3.Distance(vertPos, camPos)
float Distance = saturate((_MaxDistance/distance(i.posWorld.rgb,_WorldSpaceCameraPos)));

//Get the diffuse color
float3 dcolor = lerp(color.rgb,max(saturate((color.rgb > 0.5 ?  (1.0-(1.0-2.0*(color.rgb-0.5))*1.0-_RingDetail_var.r)) : (2.0*color.rgb*_RingDetail_var.r)) ),(_DustLarge_var.rgb+_DustSmall_var.rgb)),Distance);

/*
Color dcolor = Color.Lerp(
	(main texture W.O. effects),
    (main texture W. effects),
    Distance);

(main texture W. effects) = max(
	Mathf.Clamp01(
    (color.rgb > 0.5 ?
    (1.0-(1.0-2.0*(color.rgb-0.5))*1.0-_RingDetail_var.r)) : 
    (2.0*color.rgb*_RingDetail_var.r))),
    (_DustLarge_var.rgb+_DustSmall_var.rgb))
    
    Ergo blend mainTex and ringDetail with a hard light mode, then feed the result and the sum of the dust textures to a max function so the dust is applied on top of the ring texture.
*/


// Combine material color with texture color and shadow
dcolor.xyz = _Color * shadow * (dcolor.xyz * dotLight + dcolor.xyz * mieScattering);

fixed4 finalRGBA = fixed4(finalColor,lerp(color.a,(color.a*_RingDetail_var.g),Distance));

return finalRGBA;

I'm not sure about the way I handled the alpha channel, I'm afraid I'm shooting @blackrack's amazing scattering effect in the foot there.

This is the full edited shader:

Spoiler

// Ring shader for Kopernicus
// by Ghassen Lahmar (blackrack)

Shader "Kopernicus/Rings"
{
	SubShader
	{
		Tags
		{
			"Queue" = "Transparent"
			"IgnoreProjector" = "True"
			"RenderType" = "Transparent"
		}

		Pass
		{
			ZWrite On
			Cull Back
			// Alpha blend
			Blend SrcAlpha OneMinusSrcAlpha

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma glsl
			#pragma target 3.0

			#include "UnityCG.cginc"

			// These properties are the global inputs shared by all pixels

			uniform sampler2D _MainTex;

			uniform float innerRadius;
			uniform float outerRadius;

			uniform float planetRadius;
			uniform float sunRadius;

			uniform float3 sunPosRelativeToPlanet;

			uniform float penumbraMultiplier;

			// Unity will set this to the material color automatically
			uniform float4 _Color;

			// Properties to simulate a shade moving past the inner surface of the ring
			uniform sampler2D _InnerShadeTexture;
			uniform int       innerShadeTiles;
			uniform float     innerShadeOffset;

			#define M_PI 3.1415926535897932384626
			
			
			//Values for the detail setup
			uniform sampler2D _DustLarge;
			uniform sampler2D _DustSmall;
			uniform sampler2D _RingDetail;
			uniform float _MaxDistance;

			// This structure defines the inputs for each pixel
			struct v2f
			{
				float4 pos:          SV_POSITION;
				float3 worldPos:     TEXCOORD0;
				// Moved from fragment shader
				float3 planetOrigin: TEXCOORD1;
				float2 texCoord:     TEXCOORD2;
			};

			// Set up the inputs for the fragment shader
			v2f vert(appdata_base v)
			{
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP,    v.vertex);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				o.planetOrigin = mul(unity_ObjectToWorld, float4(0, 0, 0, 1)).xyz;
				o.texCoord = v.texcoord;
				return o;
			}

			// Mie scattering
			// Copied from Scatterer/Proland
			float PhaseFunctionM(float mu, float mieG)
			{
				// Mie phase function
				return 1.5 * 1.0 / (4.0 * M_PI) * (1.0 - mieG * mieG) * pow(1.0 + (mieG * mieG) - 2.0 * mieG * mu, -3.0 / 2.0) * (1.0 + mu * mu) / (2.0 + mieG * mieG);
			}

			// Eclipse function from Scatterer
			// Used here to cast the planet shadow on the ring
			// Will simplify it later and keep only the necessary bits for the ring
			// Original Source:   wikibooks.org/wiki/GLSL_Programming/Unity/Soft_Shadows_of_Spheres
			float getEclipseShadow(float3 worldPos, float3 worldLightPos, float3 occluderSpherePosition, float3 occluderSphereRadius, float3 lightSourceRadius)
			{
				float3 lightDirection = float3(worldLightPos - worldPos);
				float3 lightDistance = length(lightDirection);
				lightDirection = lightDirection / lightDistance;

				// Computation of level of shadowing w
				// Occluder planet
				float3 sphereDirection = float3(occluderSpherePosition - worldPos);
				float  sphereDistance = length(sphereDirection);
				sphereDirection = sphereDirection / sphereDistance;

				float dd = lightDistance * (asin(min(1.0, length(cross(lightDirection, sphereDirection)))) - asin(min(1.0, occluderSphereRadius / sphereDistance)));

				float w = smoothstep(-1.0, 1.0, -dd / lightSourceRadius)
					* smoothstep(0.0, 0.2, dot(lightDirection, sphereDirection));

				return (1 - w);
			}

			// Check whether our shadow squares cover this pixel
			float getInnerShadeShadow(v2f i)
			{
				// The shade only slides around the ring, so we use the X tex coord.
				float2 shadeTexCoord = float2(
					i.texCoord.x,
					i.texCoord.y / innerShadeTiles + innerShadeOffset
					);
				// Check the pixel currently above the one we're rendering.
				float4 shadeColor = tex2D(_InnerShadeTexture, shadeTexCoord);
				// If the shade is solid, then it blocks the light.
				// If it's transparent, then the light goes through.
				return 1 - 0.8 * shadeColor.a;
			}

			// Either we're a sun with a ringworld and shadow squares,
			// or we're a planet orbiting a sun and casting shadows.
			// There's no middle ground. So if shadow squares are turned on,
			// disable eclipse shadows.
			float getShadow(v2f i)
			{
				if (innerShadeTiles > 0) {
					return getInnerShadeShadow(i);
				}
				else {
					// Do everything relative to planet position
					// *6000 to convert to local space, might be simpler in scaled?
					float3 worldPosRelPlanet = i.worldPos - i.planetOrigin;
					return getEclipseShadow(worldPosRelPlanet * 6000, sunPosRelativeToPlanet, 0, planetRadius, sunRadius * penumbraMultiplier);
				}
			}

			// Choose a color to use for the pixel represented by 'i'
			float4 frag(v2f i) : COLOR
			{
				// Lighting
				// Fix this for additional lights later, will be useful when I do the Planetshine update for Scatterer
				// Assuming directional light only for now
				float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

				// Instead use the viewing direction (inspired from observing space engine rings)
				// Looks more interesting than I expected
				float3 viewdir = normalize(i.worldPos - _WorldSpaceCameraPos);
				float  mu = dot(lightDir, -viewdir);
				float  dotLight = 0.5 * (mu + 1);

				// Mie scattering through rings when observed from the back
				// Needs to be negative?
				float mieG = -0.95;
				// Result too bright for some reason, the 0.03 fixes it
				float mieScattering = 0.03 * PhaseFunctionM(mu, mieG);

				// Planet shadow on ring, or inner shade shadow on inner face
				float shadow = getShadow(i);

				//TODO: Fade in some noise here when getting close to the rings
				//      Make it procedural noise?

				// Look up the texture color
				float4 color = tex2D(_MainTex, i.texCoord);
				
				float4 _RingDetail_var = tex2D(_RingDetail, i.texCoord);
				float4 _DustLarge_var = tex2D(_DustLarge, i.texCoord);
				float4 _DustSmall_var = tex2D(_DustSmall, i.texCoord);
				
				
				
				
				
				
				//Here we add the detail.
				
				//Get and clamp distance between vert and camera
				float Distance = saturate((_MaxDistance/distance(i.posWorld.rgb,_WorldSpaceCameraPos)));
				
				//Get the resulting diffuse color
				float3 dcolor = lerp(
				/*The main tex, ring is unaffected if we're too far*/
				color.rgb,
				/*The effects applied to the ring tex*/
				max(saturate((color.rgb > 0.5 ?  (1.0-(1.0-2.0*(color.rgb-0.5))*(1.0-_RingDetail_var.r)) : (2.0*color.rgb*_RingDetail_var.r)) ),(_DustLarge_var.rgb+_DustSmall_var.rgb))
				/*And lastly, distance, to choose whether we need detail or not.*/
				,Distance);
				
				
				// Combine material color with texture color and shadow
				dcolor.xyz = _Color * shadow * (dcolor.xyz * dotLight + dcolor.xyz * mieScattering);

				// I'm kinda proud of this shader so far, it's short and clean
				
				
				
				fixed4 finalRGBA = fixed4(finalColor,lerp(color.a,(color.a*_RingDetail_var.g),Distance));
				
				return finalRGBA;
			}
			ENDCG
		}
	}
}

 

Could someone check my edits for errors? Of course, I'll be testing this shader, but if someone spots a flaw in advance, then I can fix it right away.

Share this post


Link to post
Share on other sites

I compiled the new ring shader into the asset bundles used by Kopernicus. Now all left to do is downloading a non-compiled copy of Kopernicus from GitHub and updating the ring spawner and ring loader codes to account for the new values.

The edited shader has been tested in Unity. It looks a bit strange and color-less, but then again it's not designed to be used standalone.

Share this post


Link to post
Share on other sites

hey, you guys know the bug where the day side of your planet doesn't align with the sun? The weird shine on the side of your planet? I've forgotten how to fix that, help plis. :I

Share this post


Link to post
Share on other sites

Still no progress on my front, should I reupload the log stuff? Because so far I haven't been able to figure out a fix. One of the logs said something about an "Unknown char" if that helps at all.

Share this post


Link to post
Share on other sites
1 hour ago, Walesdark said:

hey, you guys know the bug where the day side of your planet doesn't align with the sun? The weird shine on the side of your planet? I've forgotten how to fix that, help plis. :I

You probably didn’t make your normal map correctly.

Share this post


Link to post
Share on other sites
33 minutes ago, suomynonA said:

Still no progress on my front, should I reupload the log stuff? Because so far I haven't been able to figure out a fix. One of the logs said something about an "Unknown char" if that helps at all.

ambientColor = 0.4,0.4,0.5.1.0
                                                      ^

There is your problem, you need a , there, otherwise it isn't a valid color for KSP.

Share this post


Link to post
Share on other sites
36 minutes ago, Thomas P. said:

ambientColor = 0.4,0.4,0.5.1.0
                                                      ^

There is your problem, you need a , there, otherwise it isn't a valid color for KSP.

Thanks! Cant believe I missed something like that... It gets in-game now, but is just a white ball, I feel like there are already answers to that problem though so I'll look through the thread a bit.

Share this post


Link to post
Share on other sites
21 hours ago, Galileo said:

You probably didn’t make your normal map correctly.

how do i make it properly? i've tried to fix it for a while now and can't

Share this post


Link to post
Share on other sites

Anyone know why my Saturn looks like this in RSS? It has a moire pattern and no shadow on the rings. I'm using 1.2.2 on Macos High Sierra, using the backported version of Kopernicus for 1.2.2. It was working fine and then all of a sudden started doing this. Log here.

 

Share this post


Link to post
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.