mirror of
https://github.com/drewcassidy/KSP-Conformal-Decals.git
synced 2024-09-01 18:23:54 +00:00
Big refactor to enable preview materials
• add shader variants for decal previewing • start to add code for part icon • refactor material properties to be serializable todo: • fix decal preview scale (need to call UpdateScale on detached state) • fix texture preview in part icon • adjust culling per-object when rendering (turns out cull and ztest values are used by unity at the render time, not by the shader itself, so they can be adjusted in material property blocks!)
This commit is contained in:
parent
6c20675a99
commit
e9c8f3dafb
3
.gitignore
vendored
3
.gitignore
vendored
@ -10,6 +10,9 @@ Logs/
|
||||
Packages/
|
||||
ProjectSettings/
|
||||
Temp/
|
||||
Distribution/GameData/ConformalDecals/Resources/Resources
|
||||
Distribution/GameData/ConformalDecals/Resources/Resources.manifest
|
||||
Distribution/GameData/ConformalDecals/Resources/conformaldecals.shab.manifest
|
||||
|
||||
# Unity Project Files
|
||||
PartTools.cfg
|
||||
|
@ -4,13 +4,17 @@ Shader "ConformalDecals/Feature/Bumped"
|
||||
{
|
||||
[Header(Texture Maps)]
|
||||
_Decal("Decal Texture", 2D) = "gray" {}
|
||||
_BumpMap("Decal Bump Map", 2D) = "bump" {}
|
||||
_DecalBumpMap("Decal Bump Map", 2D) = "bump" {}
|
||||
|
||||
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
|
||||
_Opacity("_Opacity", Range(0,1) ) = 1
|
||||
_DecalOpacity("Opacity", Range(0,1) ) = 1
|
||||
_Background("Background Color", Color) = (0.9,0.9,0.9,0.7)
|
||||
|
||||
[Enum(UnityEngine.Rendering.CullMode)] _Cull ("Cull", Float) = 0
|
||||
[Toggle(DECAL_PREVIEW)] _Preview ("Preview", Float) = 0
|
||||
|
||||
[Header(Effects)]
|
||||
[PerRendererData]_Opacity("_Opacity", Range(0,1) ) = 1
|
||||
[PerRendererData]_Opacity("_Opacity", Range(0,1) ) = 1
|
||||
[PerRendererData]_RimFalloff("_RimFalloff", Range(0.01,5) ) = 0.1
|
||||
[PerRendererData]_RimColor("_RimColor", Color) = (0,0,0,0)
|
||||
[PerRendererData]_UnderwaterFogFactor ("Underwater Fog Factor", Range(0,1)) = 0
|
||||
@ -18,9 +22,9 @@ Shader "ConformalDecals/Feature/Bumped"
|
||||
SubShader
|
||||
{
|
||||
Tags { "Queue" = "Geometry+100" }
|
||||
Cull Off
|
||||
Zwrite Off
|
||||
Ztest LEqual
|
||||
Cull [_Cull]
|
||||
Ztest LEqual
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "FORWARD"
|
||||
@ -32,15 +36,14 @@ Shader "ConformalDecals/Feature/Bumped"
|
||||
#pragma fragment frag_forward
|
||||
|
||||
#pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap
|
||||
#pragma multi_compile DECAL_PROJECT DECAL_PREVIEW
|
||||
|
||||
sampler2D _Decal;
|
||||
sampler2D _BumpMap;
|
||||
sampler2D _DecalBumpMap;
|
||||
|
||||
float4 _Decal_ST;
|
||||
float4 _BumpMap_ST;
|
||||
|
||||
float _Cutoff;
|
||||
float _Opacity;
|
||||
float4 _DecalBumpMap_ST;
|
||||
|
||||
float _RimFalloff;
|
||||
float4 _RimColor;
|
||||
|
||||
@ -55,16 +58,18 @@ Shader "ConformalDecals/Feature/Bumped"
|
||||
void surf (DecalSurfaceInput IN, inout SurfaceOutput o)
|
||||
{
|
||||
float4 color = tex2D(_Decal, IN.uv_decal);
|
||||
float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv_bump));
|
||||
float3 normal = UnpackNormal(tex2D(_DecalBumpMap, IN.uv_bump));
|
||||
|
||||
// clip alpha
|
||||
clip(color.a - saturate(_Cutoff + 0.01));
|
||||
#ifdef DECAL_PROJECT
|
||||
// clip alpha
|
||||
clip(color.a - _Cutoff + 0.01);
|
||||
#endif //DECAL_PROJECT
|
||||
|
||||
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), normal));
|
||||
float3 emission = (_RimColor.rgb * pow(rim, _RimFalloff)) * _RimColor.a;
|
||||
|
||||
o.Albedo = UnderwaterFog(IN.worldPosition, color).rgb;
|
||||
o.Alpha = color.a * _Opacity;
|
||||
o.Alpha = color.a * _DecalOpacity;
|
||||
o.Emission = emission;
|
||||
o.Normal = normal;
|
||||
}
|
||||
@ -83,15 +88,14 @@ Shader "ConformalDecals/Feature/Bumped"
|
||||
#pragma fragment frag_forward
|
||||
|
||||
#pragma multi_compile_fwdadd nolightmap nodirlightmap nodynlightmap
|
||||
#pragma multi_compile DECAL_PROJECT DECAL_PREVIEW
|
||||
|
||||
sampler2D _Decal;
|
||||
sampler2D _BumpMap;
|
||||
sampler2D _DecalBumpMap;
|
||||
|
||||
float4 _Decal_ST;
|
||||
float4 _BumpMap_ST;
|
||||
float4 _DecalBumpMap_ST;
|
||||
|
||||
float _Cutoff;
|
||||
float _Opacity;
|
||||
float _RimFalloff;
|
||||
float4 _RimColor;
|
||||
|
||||
@ -106,16 +110,18 @@ Shader "ConformalDecals/Feature/Bumped"
|
||||
void surf (DecalSurfaceInput IN, inout SurfaceOutput o)
|
||||
{
|
||||
float4 color = tex2D(_Decal, IN.uv_decal);
|
||||
float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv_bump));
|
||||
float3 normal = UnpackNormal(tex2D(_DecalBumpMap, IN.uv_bump));
|
||||
|
||||
// clip alpha
|
||||
clip(color.a - saturate(_Cutoff + 0.01));
|
||||
#ifdef DECAL_PROJECT
|
||||
// clip alpha
|
||||
clip(color.a - _Cutoff + 0.01);
|
||||
#endif //DECAL_PROJECT
|
||||
|
||||
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), normal));
|
||||
float3 emission = (_RimColor.rgb * pow(rim, _RimFalloff)) * _RimColor.a;
|
||||
|
||||
o.Albedo = UnderwaterFog(IN.worldPosition, color).rgb;
|
||||
o.Alpha = color.a * _Opacity;
|
||||
o.Alpha = color.a * _DecalOpacity;
|
||||
o.Emission = emission;
|
||||
o.Normal = normal;
|
||||
}
|
||||
|
@ -6,24 +6,27 @@ Shader "ConformalDecals/Paint/Diffuse"
|
||||
_Decal("Decal Texture", 2D) = "gray" {}
|
||||
_BumpMap("Bump Map", 2D) = "bump" {}
|
||||
|
||||
_EdgeWearStrength("Edge Wear Strength", Range(0,100)) = 0
|
||||
_EdgeWearOffset("Edge Wear Offset", Range(0,1)) = 0
|
||||
_EdgeWearStrength("Edge Wear Strength", Range(0,500)) = 100
|
||||
_EdgeWearOffset("Edge Wear Offset", Range(0,1)) = 0.1
|
||||
|
||||
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
|
||||
_Opacity("_Opacity", Range(0,1) ) = 1
|
||||
_DecalOpacity("Opacity", Range(0,1) ) = 1
|
||||
_Background("Background Color", Color) = (0.9,0.9,0.9,0.7)
|
||||
|
||||
[Enum(UnityEngine.Rendering.CullMode)] _Cull ("Cull", Float) = 0
|
||||
[Toggle(DECAL_PREVIEW)] _Preview ("Preview", Float) = 0
|
||||
|
||||
[Header(Effects)]
|
||||
[PerRendererData]_Opacity("_Opacity", Range(0,1) ) = 1
|
||||
[PerRendererData]_Opacity("_Opacity", Range(0,1) ) = 1
|
||||
[PerRendererData]_RimFalloff("_RimFalloff", Range(0.01,5) ) = 0.1
|
||||
[PerRendererData]_RimColor("_RimColor", Color) = (0,0,0,0)
|
||||
[PerRendererData]_UnderwaterFogFactor ("Underwater Fog Factor", Range(0,1)) = 0
|
||||
}
|
||||
SubShader
|
||||
{
|
||||
Tags { "Queue" = "Geometry+400" }
|
||||
ZWrite Off
|
||||
ZTest LEqual
|
||||
Offset -1, -1
|
||||
Tags { "Queue" = "Geometry+100" }
|
||||
Cull [_Cull]
|
||||
Ztest LEqual
|
||||
|
||||
Pass
|
||||
{
|
||||
@ -36,18 +39,15 @@ Shader "ConformalDecals/Paint/Diffuse"
|
||||
#pragma fragment frag_forward
|
||||
|
||||
#pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap
|
||||
#pragma multi_compile __ DECAL_PREVIEW
|
||||
|
||||
sampler2D _Decal;
|
||||
sampler2D _BumpMap;
|
||||
|
||||
float4 _Decal_ST;
|
||||
float4 _BumpMap_ST;
|
||||
|
||||
float _EdgeWearStrength;
|
||||
float _EdgeWearOffset;
|
||||
|
||||
float _Cutoff;
|
||||
float _Opacity;
|
||||
|
||||
float _RimFalloff;
|
||||
float4 _RimColor;
|
||||
|
||||
@ -62,11 +62,10 @@ Shader "ConformalDecals/Paint/Diffuse"
|
||||
void surf (DecalSurfaceInput IN, inout SurfaceOutput o)
|
||||
{
|
||||
float4 color = tex2D(_Decal, IN.uv_decal);
|
||||
float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv_base));
|
||||
|
||||
// clip alpha
|
||||
clip(color.a - _Cutoff);
|
||||
decalClipAlpha(color.a);
|
||||
|
||||
float3 normal = IN.normal;
|
||||
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), normal));
|
||||
float3 emission = (_RimColor.rgb * pow(rim, _RimFalloff)) * _RimColor.a;
|
||||
|
||||
@ -76,9 +75,8 @@ Shader "ConformalDecals/Paint/Diffuse"
|
||||
color.a *= saturate(1 + _EdgeWearOffset - saturate(_EdgeWearStrength * wearFactor));
|
||||
|
||||
o.Albedo = UnderwaterFog(IN.worldPosition, color).rgb;
|
||||
o.Alpha = color.a * _Opacity;
|
||||
o.Alpha = color.a * _DecalOpacity;
|
||||
o.Emission = emission;
|
||||
o.Normal = normal;
|
||||
}
|
||||
|
||||
ENDCG
|
||||
@ -95,18 +93,15 @@ Shader "ConformalDecals/Paint/Diffuse"
|
||||
#pragma fragment frag_forward
|
||||
|
||||
#pragma multi_compile_fwdadd nolightmap nodirlightmap nodynlightmap
|
||||
#pragma multi_compile __ DECAL_PREVIEW
|
||||
|
||||
sampler2D _Decal;
|
||||
sampler2D _BumpMap;
|
||||
|
||||
float4 _Decal_ST;
|
||||
float4 _BumpMap_ST;
|
||||
|
||||
float _EdgeWearStrength;
|
||||
float _EdgeWearOffset;
|
||||
|
||||
float _Cutoff;
|
||||
float _Opacity;
|
||||
float _RimFalloff;
|
||||
float4 _RimColor;
|
||||
|
||||
@ -121,11 +116,10 @@ Shader "ConformalDecals/Paint/Diffuse"
|
||||
void surf (DecalSurfaceInput IN, inout SurfaceOutput o)
|
||||
{
|
||||
float4 color = tex2D(_Decal, IN.uv_decal);
|
||||
float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv_base));
|
||||
|
||||
// clip alpha
|
||||
clip(color.a - _Cutoff);
|
||||
decalClipAlpha(color.a);
|
||||
|
||||
float3 normal = IN.normal;
|
||||
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), normal));
|
||||
float3 emission = (_RimColor.rgb * pow(rim, _RimFalloff)) * _RimColor.a;
|
||||
|
||||
@ -135,9 +129,8 @@ Shader "ConformalDecals/Paint/Diffuse"
|
||||
color.a *= saturate(1 + _EdgeWearOffset - saturate(_EdgeWearStrength * wearFactor));
|
||||
|
||||
o.Albedo = UnderwaterFog(IN.worldPosition, color).rgb;
|
||||
o.Alpha = color.a * _Opacity;
|
||||
o.Alpha = color.a * _DecalOpacity;
|
||||
o.Emission = emission;
|
||||
o.Normal = normal;
|
||||
}
|
||||
|
||||
ENDCG
|
||||
|
@ -7,16 +7,19 @@ Shader "ConformalDecals/Paint/Specular"
|
||||
_BumpMap("Bump Map", 2D) = "bump" {}
|
||||
_SpecMap("Specular Map", 2D) = "black" {}
|
||||
|
||||
_EdgeWearStrength("Edge Wear Strength", Range(0,100)) = 0
|
||||
_EdgeWearOffset("Edge Wear Offset", Range(0,1)) = 0
|
||||
_EdgeWearStrength("Edge Wear Strength", Range(0,500)) = 100
|
||||
_EdgeWearOffset("Edge Wear Offset", Range(0,1)) = 0.1
|
||||
|
||||
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
|
||||
_Opacity("_Opacity", Range(0,1) ) = 1
|
||||
_DecalOpacity("Opacity", Range(0,1) ) = 1
|
||||
_Background("Background Color", Color) = (0.9,0.9,0.9,0.7)
|
||||
|
||||
[Header(Specularity)]
|
||||
_SpecColor ("_SpecColor", Color) = (0.5, 0.5, 0.5, 1)
|
||||
_Shininess ("Shininess", Range (0.03, 10)) = 0.4
|
||||
_SpecColor ("_SpecColor", Color) = (0.25, 0.25, 0.25, 1)
|
||||
_Shininess ("Shininess", Range (0.03, 10)) = 0.3
|
||||
|
||||
[Enum(UnityEngine.Rendering.CullMode)] _Cull ("Cull", Float) = 0
|
||||
[Toggle(DECAL_PREVIEW)] _Preview ("Preview", Float) = 0
|
||||
|
||||
[Header(Effects)]
|
||||
[PerRendererData]_Opacity("_Opacity", Range(0,1) ) = 1
|
||||
@ -26,10 +29,9 @@ Shader "ConformalDecals/Paint/Specular"
|
||||
}
|
||||
SubShader
|
||||
{
|
||||
Tags { "Queue" = "Geometry+400" }
|
||||
ZWrite Off
|
||||
ZTest LEqual
|
||||
Offset -1, -1
|
||||
Tags { "Queue" = "Geometry+100" }
|
||||
Cull [_Cull]
|
||||
Ztest LEqual
|
||||
|
||||
Pass
|
||||
{
|
||||
@ -42,22 +44,19 @@ Shader "ConformalDecals/Paint/Specular"
|
||||
#pragma fragment frag_forward
|
||||
|
||||
#pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap
|
||||
#pragma multi_compile __ DECAL_PREVIEW
|
||||
|
||||
sampler2D _Decal;
|
||||
sampler2D _BumpMap;
|
||||
sampler2D _SpecMap;
|
||||
|
||||
float4 _Decal_ST;
|
||||
float4 _BumpMap_ST;
|
||||
float4 _SpecMap_ST;
|
||||
|
||||
float _EdgeWearStrength;
|
||||
float _EdgeWearOffset;
|
||||
|
||||
half _Shininess;
|
||||
|
||||
float _Cutoff;
|
||||
float _Opacity;
|
||||
|
||||
float _RimFalloff;
|
||||
float4 _RimColor;
|
||||
|
||||
@ -73,11 +72,13 @@ Shader "ConformalDecals/Paint/Specular"
|
||||
void surf (DecalSurfaceInput IN, inout SurfaceOutput o)
|
||||
{
|
||||
float4 color = tex2D(_Decal, IN.uv_decal);
|
||||
float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv_base));
|
||||
float3 specular = tex2D(_SpecMap, IN.uv_spec);
|
||||
|
||||
// clip alpha
|
||||
clip(color.a - _Cutoff);
|
||||
float3 normal = IN.normal;
|
||||
|
||||
#ifdef DECAL_PROJECT
|
||||
// clip alpha
|
||||
clip(color.a - _Cutoff + 0.01);
|
||||
#endif //DECAL_PROJECT
|
||||
|
||||
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), normal));
|
||||
float3 emission = (_RimColor.rgb * pow(rim, _RimFalloff)) * _RimColor.a;
|
||||
@ -86,12 +87,11 @@ Shader "ConformalDecals/Paint/Specular"
|
||||
float wearFactorAlpha = saturate(_EdgeWearStrength * wearFactor);
|
||||
|
||||
color.a *= saturate(1 + _EdgeWearOffset - saturate(_EdgeWearStrength * wearFactor));
|
||||
color.a *= _Opacity;
|
||||
color.a *= _DecalOpacity;
|
||||
|
||||
o.Albedo = UnderwaterFog(IN.worldPosition, color).rgb;
|
||||
o.Alpha = color.a;
|
||||
o.Emission = emission;
|
||||
o.Normal = normal;
|
||||
o.Specular = _Shininess;
|
||||
o.Gloss = specular.r * color.a;
|
||||
}
|
||||
@ -110,22 +110,19 @@ Shader "ConformalDecals/Paint/Specular"
|
||||
#pragma fragment frag_forward
|
||||
|
||||
#pragma multi_compile_fwdadd nolightmap nodirlightmap nodynlightmap
|
||||
|
||||
#pragma multi_compile __ DECAL_PREVIEW
|
||||
|
||||
sampler2D _Decal;
|
||||
sampler2D _BumpMap;
|
||||
sampler2D _SpecMap;
|
||||
|
||||
float4 _Decal_ST;
|
||||
float4 _BumpMap_ST;
|
||||
float4 _SpecMap_ST;
|
||||
|
||||
float _EdgeWearStrength;
|
||||
float _EdgeWearOffset;
|
||||
|
||||
half _Shininess;
|
||||
|
||||
float _Cutoff;
|
||||
float _Opacity;
|
||||
|
||||
float _RimFalloff;
|
||||
float4 _RimColor;
|
||||
|
||||
@ -141,11 +138,13 @@ Shader "ConformalDecals/Paint/Specular"
|
||||
void surf (DecalSurfaceInput IN, inout SurfaceOutput o)
|
||||
{
|
||||
float4 color = tex2D(_Decal, IN.uv_decal);
|
||||
float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv_base));
|
||||
float3 specular = tex2D(_SpecMap, IN.uv_spec);
|
||||
float3 normal = IN.normal;
|
||||
|
||||
// clip alpha
|
||||
clip(color.a - _Cutoff);
|
||||
#ifdef DECAL_PROJECT
|
||||
// clip alpha
|
||||
clip(color.a - _Cutoff + 0.01);
|
||||
#endif //DECAL_PROJECT
|
||||
|
||||
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), normal));
|
||||
float3 emission = (_RimColor.rgb * pow(rim, _RimFalloff)) * _RimColor.a;
|
||||
@ -156,9 +155,8 @@ Shader "ConformalDecals/Paint/Specular"
|
||||
color.a *= saturate(1 + _EdgeWearOffset - saturate(_EdgeWearStrength * wearFactor));
|
||||
|
||||
o.Albedo = UnderwaterFog(IN.worldPosition, color).rgb;
|
||||
o.Alpha = color.a * _Opacity;
|
||||
o.Alpha = color.a * _DecalOpacity;
|
||||
o.Emission = emission;
|
||||
o.Normal = normal;
|
||||
o.Specular = _Shininess;
|
||||
o.Gloss = specular.r;
|
||||
}
|
||||
|
@ -18,10 +18,9 @@ struct DecalSurfaceInput
|
||||
#endif //DECAL_EMISSIVE
|
||||
|
||||
#ifdef DECAL_BASE_NORMAL
|
||||
float2 uv_base;
|
||||
#endif //DECAL_BASE_NORMAL
|
||||
float3 normal;
|
||||
#endif
|
||||
|
||||
float3 normal;
|
||||
float3 viewDir;
|
||||
float3 worldPosition;
|
||||
};
|
||||
@ -30,10 +29,10 @@ struct appdata_decal
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
#ifdef DECAL_BASE_NORMAL
|
||||
#if defined(DECAL_BASE_NORMAL) || defined(DECAL_PREVIEW)
|
||||
float4 texcoord : TEXCOORD0;
|
||||
float4 tangent : TANGENT;
|
||||
#endif //DECAL_BASE_NORMAL
|
||||
#endif
|
||||
};
|
||||
|
||||
struct v2f
|
||||
@ -65,6 +64,23 @@ float4x4 _ProjectionMatrix;
|
||||
float3 _DecalNormal;
|
||||
float3 _DecalTangent;
|
||||
|
||||
#ifdef DECAL_BASE_NORMAL
|
||||
sampler2D _BumpMap;
|
||||
float4 _BumpMap_ST;
|
||||
#endif //DECAL_BASE_NORMAL
|
||||
|
||||
float _Cutoff;
|
||||
float _DecalOpacity;
|
||||
|
||||
float _Opacity;
|
||||
float4 _Background;
|
||||
|
||||
inline void decalClipAlpha(float alpha) {
|
||||
#ifndef DECAL_PREVIEW
|
||||
clip(alpha - _Cutoff + 0.01);
|
||||
#endif
|
||||
}
|
||||
|
||||
// declare surf function,
|
||||
// this must be defined in any shader using this cginc
|
||||
void surf (DecalSurfaceInput IN, inout SurfaceOutput o);
|
||||
@ -76,7 +92,12 @@ v2f vert_forward(appdata_decal v)
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.normal = v.normal;
|
||||
o.uv_decal = mul (_ProjectionMatrix, v.vertex);
|
||||
|
||||
#ifdef DECAL_PREVIEW
|
||||
o.uv_decal = v.texcoord;
|
||||
#else
|
||||
o.uv_decal = mul (_ProjectionMatrix, v.vertex);
|
||||
#endif //DECAL_PREVIEW
|
||||
|
||||
#ifdef DECAL_BASE_NORMAL
|
||||
o.uv_base = TRANSFORM_TEX(v.texcoord, _BumpMap);
|
||||
@ -85,7 +106,7 @@ v2f vert_forward(appdata_decal v)
|
||||
float3 worldPosition = mul(unity_ObjectToWorld, v.vertex).xyz;
|
||||
float3 worldNormal = UnityObjectToWorldNormal(v.normal);
|
||||
|
||||
#ifdef DECAL_BASE_NORMAL
|
||||
#if defined(DECAL_BASE_NORMAL) || defined(DECAL_PREVIEW)
|
||||
// use tangent of base geometry
|
||||
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
|
||||
fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
|
||||
@ -95,7 +116,7 @@ v2f vert_forward(appdata_decal v)
|
||||
fixed3 decalTangent = UnityObjectToWorldDir(_DecalTangent);
|
||||
fixed3 worldBinormal = cross(decalTangent, worldNormal);
|
||||
fixed3 worldTangent = cross(worldNormal, worldBinormal);
|
||||
#endif //DECAL_BASE_NORMAL
|
||||
#endif //defined(DECAL_BASE_NORMAL) || defined(DECAL_PREVIEW)
|
||||
|
||||
o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPosition.x);
|
||||
o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPosition.y);
|
||||
@ -148,22 +169,26 @@ fixed4 frag_forward(v2f IN) : SV_Target
|
||||
float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPosition));
|
||||
float3 viewDir = _unity_tbn_0 * worldViewDir.x + _unity_tbn_1 * worldViewDir.y + _unity_tbn_2 * worldViewDir.z;
|
||||
|
||||
// perform decal projection
|
||||
fixed4 uv_projected = UNITY_PROJ_COORD(IN.uv_decal);
|
||||
#ifdef DECAL_PREVIEW
|
||||
fixed4 uv_projected = IN.uv_decal;
|
||||
#else
|
||||
// perform decal projection
|
||||
fixed4 uv_projected = UNITY_PROJ_COORD(IN.uv_decal);
|
||||
|
||||
// clip texture outside of xyz bounds
|
||||
clip(uv_projected.xyz);
|
||||
clip(1-uv_projected.xyz);
|
||||
|
||||
// clip backsides
|
||||
clip(dot(_DecalNormal, IN.normal));
|
||||
// clip texture outside of xyz bounds
|
||||
clip(uv_projected.xyz);
|
||||
clip(1-uv_projected.xyz);
|
||||
|
||||
// clip backsides
|
||||
clip(dot(_DecalNormal, IN.normal));
|
||||
#endif //DECAL_PREVIEW
|
||||
|
||||
// initialize surface input
|
||||
UNITY_INITIALIZE_OUTPUT(DecalSurfaceInput, i)
|
||||
i.uv_decal = TRANSFORM_TEX(uv_projected, _Decal);
|
||||
|
||||
#ifdef DECAL_NORMAL
|
||||
i.uv_bump = TRANSFORM_TEX(uv_projected, _BumpMap);
|
||||
i.uv_bump = TRANSFORM_TEX(uv_projected, _DecalBumpMap);
|
||||
#endif //DECAL_NORMAL
|
||||
|
||||
#ifdef DECAL_SPECULAR
|
||||
@ -173,12 +198,16 @@ fixed4 frag_forward(v2f IN) : SV_Target
|
||||
#ifdef DECAL_EMISSIVE
|
||||
i.uv_glow = TRANSFORM_TEX(uv_projected, _GlowMap);
|
||||
#endif //DECAL_EMISSIVE
|
||||
|
||||
#ifdef DECAL_BASE_NORMAL
|
||||
i.uv_base = IN.uv_base;
|
||||
#endif //DECAL_BASE_NORMAL
|
||||
|
||||
i.normal = IN.normal;
|
||||
#ifdef DECAL_BASE_NORMAL
|
||||
#ifdef DECAL_PREVIEW
|
||||
i.normal = fixed3(0,0,1);
|
||||
#else
|
||||
i.normal = UnpackNormal(tex2D(_BumpMap, IN.uv_base));
|
||||
#endif //DECAL_PREVIEW
|
||||
#endif //DECAL_BASE_NORMAL
|
||||
|
||||
//i.normal = IN.normal;
|
||||
i.viewDir = viewDir;
|
||||
i.worldPosition = worldPosition;
|
||||
|
||||
@ -192,6 +221,14 @@ fixed4 frag_forward(v2f IN) : SV_Target
|
||||
|
||||
// call surface function
|
||||
surf(i, o);
|
||||
|
||||
#ifdef DECAL_PREVIEW
|
||||
o.Albedo = lerp(_Background.rgb,o.Albedo, o.Alpha);
|
||||
o.Normal = lerp(float3(0,0,1), o.Normal, o.Alpha);
|
||||
o.Gloss = lerp(_Background.a, o.Gloss, o.Alpha);
|
||||
o.Emission = lerp(0, o.Emission, o.Alpha);
|
||||
o.Alpha = _Opacity;
|
||||
#endif //DECAL_PREVIEW
|
||||
|
||||
// compute lighting & shadowing factor
|
||||
UNITY_LIGHT_ATTENUATION(atten, IN, worldPosition)
|
||||
@ -203,7 +240,6 @@ fixed4 frag_forward(v2f IN) : SV_Target
|
||||
WorldNormal.z = dot(_unity_tbn_2, o.Normal);
|
||||
WorldNormal = normalize(WorldNormal);
|
||||
o.Normal = WorldNormal;
|
||||
|
||||
|
||||
//KSP lighting function
|
||||
c += LightingBlinnPhongSmooth(o, lightDir, worldViewDir, atten);
|
||||
|
@ -64,18 +64,18 @@ PART
|
||||
name = ModuleConformalDecalGeneric
|
||||
}
|
||||
DATA {
|
||||
decalShader = ConformalDecals/Feature/Bumped
|
||||
shader = ConformalDecals/Feature/Bumped
|
||||
|
||||
TEXTURE {
|
||||
name = _Decal
|
||||
textureURL = ConformalDecals/Assets/Tortilla-diffuse
|
||||
textureUrl = ConformalDecals/Assets/Tortilla-diffuse
|
||||
isMain = true
|
||||
}
|
||||
|
||||
TEXTURE
|
||||
{
|
||||
name = _BumpMap
|
||||
textureURL = ConformalDecals/Assets/Tortilla-normal
|
||||
name = _DecalBumpMap
|
||||
textureUrl = ConformalDecals/Assets/Tortilla-normal
|
||||
isNormalMap = true
|
||||
}
|
||||
}
|
||||
@ -90,11 +90,11 @@ PART
|
||||
name = ModuleConformalDecalGeneric
|
||||
}
|
||||
DATA {
|
||||
decalShader = ConformalDecals/Paint/Diffuse
|
||||
shader = ConformalDecals/Paint/Diffuse
|
||||
useBaseNormal = true
|
||||
TEXTURE {
|
||||
name = _Decal
|
||||
textureURL = ConformalDecals/Assets/Sign-HighVoltage-2
|
||||
textureUrl = ConformalDecals/Assets/Sign-HighVoltage-2
|
||||
isMain = true
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
@ -3,18 +3,18 @@ using UnityEngine;
|
||||
|
||||
namespace ConformalDecals.MaterialModifiers {
|
||||
public class MaterialColorProperty : MaterialProperty {
|
||||
private readonly Color _color;
|
||||
[SerializeField] public Color color;
|
||||
|
||||
public MaterialColorProperty(ConfigNode node) : base(node) {
|
||||
_color = ParsePropertyColor(node, "color", false);
|
||||
}
|
||||
public override void ParseNode(ConfigNode node) {
|
||||
base.ParseNode(node);
|
||||
|
||||
public MaterialColorProperty(string name, Color value) : base(name) {
|
||||
_color = value;
|
||||
color = ParsePropertyColor(node, "color", true, color);
|
||||
}
|
||||
|
||||
public override void Modify(Material material) {
|
||||
material.SetColor(_propertyID, _color);
|
||||
if (material == null) throw new ArgumentNullException("material cannot be null");
|
||||
|
||||
material.SetColor(_propertyID, color);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,18 +3,18 @@ using UnityEngine;
|
||||
|
||||
namespace ConformalDecals.MaterialModifiers {
|
||||
public class MaterialFloatProperty : MaterialProperty {
|
||||
private readonly float _value;
|
||||
[SerializeField] public float value;
|
||||
|
||||
public MaterialFloatProperty(ConfigNode node) : base(node) {
|
||||
_value = ParsePropertyFloat(node, "value", false);
|
||||
}
|
||||
public override void ParseNode(ConfigNode node) {
|
||||
base.ParseNode(node);
|
||||
|
||||
public MaterialFloatProperty(string name, float value) : base(name) {
|
||||
_value = value;
|
||||
value = ParsePropertyFloat(node, "value", true, value);
|
||||
}
|
||||
|
||||
public override void Modify(Material material) {
|
||||
material.SetFloat(_propertyID, _value);
|
||||
if (material == null) throw new ArgumentNullException("material cannot be null");
|
||||
|
||||
material.SetFloat(_propertyID, value);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +1,24 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace ConformalDecals.MaterialModifiers {
|
||||
public abstract class MaterialProperty {
|
||||
public string PropertyName { get; }
|
||||
public abstract class MaterialProperty : ScriptableObject {
|
||||
public string Name {
|
||||
get => _propertyName;
|
||||
set {
|
||||
_propertyName = value;
|
||||
_propertyID = Shader.PropertyToID(_propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly int _propertyID;
|
||||
[SerializeField] protected int _propertyID;
|
||||
[SerializeField] protected string _propertyName;
|
||||
|
||||
public virtual void ParseNode(ConfigNode node) {
|
||||
if (node == null) throw new ArgumentNullException("node cannot be null");
|
||||
|
||||
protected MaterialProperty(ConfigNode node) : this(node.GetValue("name")) { }
|
||||
|
||||
protected MaterialProperty(string name) {
|
||||
if (name == null)
|
||||
throw new FormatException("name not found, cannot create material modifier");
|
||||
|
||||
if (name == string.Empty)
|
||||
throw new FormatException("name is empty, cannot create material modifier");
|
||||
|
||||
PropertyName = name;
|
||||
_propertyID = Shader.PropertyToID(PropertyName);
|
||||
Name = node.GetValue("name");
|
||||
}
|
||||
|
||||
public abstract void Modify(Material material);
|
||||
@ -57,10 +57,10 @@ namespace ConformalDecals.MaterialModifiers {
|
||||
}
|
||||
else {
|
||||
if (valueString == null)
|
||||
throw new FormatException($"Missing {typeof(T)} value for {valueName} in property '{PropertyName}'");
|
||||
throw new FormatException($"Missing {typeof(T)} value for {valueName} in property '{Name}'");
|
||||
|
||||
if (valueString == string.Empty)
|
||||
throw new FormatException($"Empty {typeof(T)} value for {valueName} in property '{PropertyName}'");
|
||||
throw new FormatException($"Empty {typeof(T)} value for {valueName} in property '{Name}'");
|
||||
}
|
||||
|
||||
if (tryParse(valueString, out var value)) {
|
||||
@ -72,7 +72,7 @@ namespace ConformalDecals.MaterialModifiers {
|
||||
}
|
||||
|
||||
else {
|
||||
throw new FormatException($"Improperly formatted {typeof(T)} value for {valueName} in property '{PropertyName}' : '{valueString}");
|
||||
throw new FormatException($"Improperly formatted {typeof(T)} value for {valueName} in property '{Name}' : '{valueString}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,18 +4,18 @@ using UnityEngine;
|
||||
|
||||
namespace ConformalDecals.MaterialModifiers {
|
||||
public class MaterialPropertyCollection : ScriptableObject {
|
||||
private static readonly int OpacityId = Shader.PropertyToID("_Opacity");
|
||||
private static readonly int OpacityId = Shader.PropertyToID("_DecalOpacity");
|
||||
private static readonly int CutoffId = Shader.PropertyToID("_Cutoff");
|
||||
|
||||
public MaterialTextureProperty MainMaterialTextureProperty { get; set; }
|
||||
public MaterialTextureProperty MainMaterialTextureProperty => _mainTexture;
|
||||
|
||||
private List<MaterialProperty> _materialProperties;
|
||||
private List<MaterialTextureProperty> _textureMaterialProperties;
|
||||
public Shader DecalShader => _shader;
|
||||
|
||||
public Material DecalMaterial {
|
||||
get {
|
||||
Debug.Log($"{_textureMaterialProperties == null}");
|
||||
if (_decalMaterial == null) {
|
||||
_decalMaterial = new Material(_decalShader);
|
||||
_decalMaterial = new Material(_shader);
|
||||
UpdateMaterial(_decalMaterial);
|
||||
}
|
||||
|
||||
@ -23,13 +23,32 @@ namespace ConformalDecals.MaterialModifiers {
|
||||
}
|
||||
}
|
||||
|
||||
public Shader DecalShader => _decalShader;
|
||||
public Material PreviewMaterial {
|
||||
get {
|
||||
if (_previewMaterial == null) {
|
||||
_previewMaterial = new Material(_shader);
|
||||
UpdateMaterial(_previewMaterial);
|
||||
_previewMaterial.EnableKeyword("DECAL_PREVIEW");
|
||||
}
|
||||
|
||||
public float AspectRatio => MainMaterialTextureProperty?.AspectRatio ?? 1f;
|
||||
return _previewMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField] private Shader _decalShader;
|
||||
public float AspectRatio {
|
||||
get {
|
||||
if (MainMaterialTextureProperty == null) return 1;
|
||||
return MainMaterialTextureProperty.AspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField] private Shader _shader;
|
||||
[SerializeField] private List<MaterialProperty> _materialProperties;
|
||||
[SerializeField] private List<MaterialTextureProperty> _textureMaterialProperties;
|
||||
[SerializeField] private MaterialTextureProperty _mainTexture;
|
||||
|
||||
private Material _decalMaterial;
|
||||
private Material _previewMaterial;
|
||||
|
||||
public void Initialize() {
|
||||
_materialProperties = new List<MaterialProperty>();
|
||||
@ -44,7 +63,7 @@ namespace ConformalDecals.MaterialModifiers {
|
||||
}
|
||||
|
||||
foreach (var p in _materialProperties) {
|
||||
if (p.PropertyName == property.PropertyName) {
|
||||
if (p.Name == property.Name) {
|
||||
_materialProperties.Remove(property);
|
||||
}
|
||||
}
|
||||
@ -53,20 +72,20 @@ namespace ConformalDecals.MaterialModifiers {
|
||||
|
||||
if (property is MaterialTextureProperty textureProperty) {
|
||||
foreach (var p in _textureMaterialProperties) {
|
||||
if (p.PropertyName == textureProperty.PropertyName) {
|
||||
if (p.Name == textureProperty.Name) {
|
||||
_textureMaterialProperties.Remove(textureProperty);
|
||||
}
|
||||
}
|
||||
|
||||
_textureMaterialProperties.Add(textureProperty);
|
||||
|
||||
if (textureProperty.IsMain) MainMaterialTextureProperty ??= textureProperty;
|
||||
if (textureProperty.isMain) _mainTexture ??= textureProperty;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetShader(string shaderName) {
|
||||
if (string.IsNullOrEmpty(shaderName)) {
|
||||
if (_decalShader == null) {
|
||||
if (_shader == null) {
|
||||
Debug.Log("Using default decal shader");
|
||||
shaderName = "ConformalDecals/Paint/Diffuse";
|
||||
}
|
||||
@ -79,13 +98,15 @@ namespace ConformalDecals.MaterialModifiers {
|
||||
|
||||
if (shader == null) throw new FormatException($"Unable to find specified shader '{shaderName}'");
|
||||
|
||||
_decalShader = shader;
|
||||
_shader = shader;
|
||||
_decalMaterial = null;
|
||||
_previewMaterial = null;
|
||||
}
|
||||
|
||||
public void SetRenderQueue(int queue) {
|
||||
DecalMaterial.renderQueue = queue;
|
||||
}
|
||||
|
||||
|
||||
public void SetScale(Vector2 scale) {
|
||||
foreach (var textureProperty in _textureMaterialProperties) {
|
||||
textureProperty.UpdateScale(DecalMaterial, scale);
|
||||
@ -101,10 +122,21 @@ namespace ConformalDecals.MaterialModifiers {
|
||||
}
|
||||
|
||||
public void UpdateMaterials() {
|
||||
if (_decalMaterial == null) {
|
||||
_decalMaterial = DecalMaterial;
|
||||
}
|
||||
|
||||
if (_previewMaterial == null) {
|
||||
_previewMaterial = PreviewMaterial;
|
||||
}
|
||||
|
||||
UpdateMaterial(_decalMaterial);
|
||||
UpdateMaterial(_previewMaterial);
|
||||
}
|
||||
|
||||
public void UpdateMaterial(Material material) {
|
||||
if (material == null) throw new ArgumentNullException("material cannot be null");
|
||||
|
||||
foreach (var property in _materialProperties) {
|
||||
property.Modify(material);
|
||||
}
|
||||
|
@ -3,29 +3,54 @@ using UnityEngine;
|
||||
|
||||
namespace ConformalDecals.MaterialModifiers {
|
||||
public class MaterialTextureProperty : MaterialProperty {
|
||||
public Texture2D texture;
|
||||
[SerializeField] public Texture2D texture;
|
||||
|
||||
public bool IsNormal { get; }
|
||||
public bool IsMain { get; }
|
||||
public bool AutoScale { get; }
|
||||
[SerializeField] public bool isNormal;
|
||||
[SerializeField] public bool isMain;
|
||||
[SerializeField] public bool autoScale;
|
||||
|
||||
private readonly Rect _tileRect;
|
||||
[SerializeField] private bool _hasTile;
|
||||
[SerializeField] private Rect _tileRect;
|
||||
[SerializeField] private Vector2 _textureOffset = Vector2.zero;
|
||||
[SerializeField] private Vector2 _textureScale = Vector2.one;
|
||||
|
||||
public float AspectRatio => _tileRect.height / _tileRect.width;
|
||||
public float AspectRatio {
|
||||
get {
|
||||
if (texture == null) return 1;
|
||||
if (!_hasTile || Mathf.Approximately(0, _tileRect.width)) return ((float) texture.height) / ((float) texture.width);
|
||||
return _tileRect.height / _tileRect.width;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Vector2 _textureOffset;
|
||||
private readonly Vector2 _textureScale;
|
||||
public Rect TileRect {
|
||||
get => _tileRect;
|
||||
set {
|
||||
_hasTile = !(Mathf.Abs(value.width) < 0.1) || !(Mathf.Abs(value.height) < 0.1);
|
||||
|
||||
public MaterialTextureProperty(ConfigNode node) : base(node) {
|
||||
IsNormal = ParsePropertyBool(node, "isNormalMap", true, PropertyName == "_BumpMap");
|
||||
IsMain = ParsePropertyBool(node, "isMain", true);
|
||||
AutoScale = ParsePropertyBool(node, "autoScale", true);
|
||||
var textureUrl = node.GetValue("textureURL");
|
||||
_tileRect = value;
|
||||
UpdateTiling();
|
||||
}
|
||||
}
|
||||
|
||||
if ((textureUrl == null && IsNormal) || textureUrl == "Bump") {
|
||||
public override void ParseNode(ConfigNode node) {
|
||||
base.ParseNode(node);
|
||||
|
||||
isNormal = ParsePropertyBool(node, "isNormalMap", true, (Name == "_BumpMap") || isNormal);
|
||||
isMain = ParsePropertyBool(node, "isMain", true, isMain);
|
||||
autoScale = ParsePropertyBool(node, "autoScale", true, autoScale);
|
||||
|
||||
SetTexture(node.GetValue("textureUrl"));
|
||||
|
||||
if (node.HasValue("tileRect")) {
|
||||
TileRect = ParsePropertyRect(node, "tileRect", true, _tileRect);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTexture(string textureUrl) {
|
||||
if ((textureUrl == null && isNormal) || textureUrl == "Bump") {
|
||||
texture = Texture2D.normalTexture;
|
||||
}
|
||||
else if ((textureUrl == null && !IsNormal) || textureUrl == "White") {
|
||||
else if ((textureUrl == null && !isNormal) || textureUrl == "White") {
|
||||
texture = Texture2D.whiteTexture;
|
||||
}
|
||||
else if (textureUrl == "Black") {
|
||||
@ -36,48 +61,43 @@ namespace ConformalDecals.MaterialModifiers {
|
||||
|
||||
if (textureInfo == null) throw new Exception($"Cannot find texture: '{textureUrl}'");
|
||||
|
||||
texture = IsNormal ? textureInfo.normalMap : textureInfo.texture;
|
||||
texture = isNormal ? textureInfo.normalMap : textureInfo.texture;
|
||||
}
|
||||
|
||||
if (texture == null) throw new Exception($"Cannot get texture from texture info '{textureUrl}' isNormalMap = {IsNormal}");
|
||||
|
||||
_tileRect = ParsePropertyRect(node, "tileRect", true, new Rect(0, 0, texture.width, texture.height));
|
||||
|
||||
_textureScale.x = _tileRect.width / texture.width;
|
||||
_textureScale.y = _tileRect.height / texture.height;
|
||||
|
||||
_textureOffset.x = _tileRect.x / texture.width;
|
||||
_textureOffset.y = _tileRect.y / texture.height;
|
||||
if (texture == null) throw new Exception($"Cannot get texture from texture info '{textureUrl}', isNormalMap = {isNormal}");
|
||||
UpdateTiling();
|
||||
}
|
||||
|
||||
public MaterialTextureProperty(string name, Texture2D texture, Rect tileRect = default,
|
||||
bool isNormal = false, bool isMain = false, bool autoScale = false) : base(name) {
|
||||
|
||||
this.texture = texture;
|
||||
|
||||
_tileRect = tileRect == default ? new Rect(0, 0, this.texture.width, this.texture.height) : tileRect;
|
||||
|
||||
IsNormal = isNormal;
|
||||
IsMain = isMain;
|
||||
AutoScale = autoScale;
|
||||
|
||||
_textureScale.x = _tileRect.width / this.texture.width;
|
||||
_textureScale.y = _tileRect.height / this.texture.height;
|
||||
|
||||
_textureOffset.x = _tileRect.x / this.texture.width;
|
||||
_textureOffset.y = _tileRect.y / this.texture.height;
|
||||
}
|
||||
|
||||
public override void Modify(Material material) {
|
||||
if (material == null) throw new ArgumentNullException(nameof(material));
|
||||
if (texture == null) {
|
||||
texture = Texture2D.whiteTexture;
|
||||
throw new NullReferenceException("texture is null, but should not be");
|
||||
}
|
||||
|
||||
material.SetTexture(_propertyID, texture);
|
||||
material.SetTextureOffset(_propertyID, _textureOffset);
|
||||
material.SetTextureScale(_propertyID, _textureScale);
|
||||
}
|
||||
|
||||
public void UpdateScale(Material material, Vector2 scale) {
|
||||
if (AutoScale) {
|
||||
if (autoScale) {
|
||||
material.SetTextureScale(_propertyID, new Vector2(_textureScale.x * scale.x, _textureScale.y * scale.y));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTiling() {
|
||||
if (_hasTile) {
|
||||
_textureScale.x = Mathf.Approximately(0, _tileRect.width) ? 1 : _tileRect.width / texture.width;
|
||||
_textureScale.y = Mathf.Approximately(0, _tileRect.height) ? 1 : _tileRect.height / texture.height;
|
||||
|
||||
_textureOffset.x = _tileRect.x / texture.width;
|
||||
_textureOffset.y = _tileRect.y / texture.height;
|
||||
}
|
||||
else {
|
||||
_textureScale = Vector2.one;
|
||||
_textureOffset = Vector2.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,26 +7,27 @@ using UnityEngine;
|
||||
namespace ConformalDecals {
|
||||
public abstract class ModuleConformalDecalBase : PartModule {
|
||||
[KSPField(guiName = "#LOC_ConformalDecals_gui-scale", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F2", guiUnits = "m"),
|
||||
UI_FloatRange(minValue = 0.05f, maxValue = 4f, stepIncrement = 0.05f)]
|
||||
UI_FloatRange(stepIncrement = 0.05f)]
|
||||
public float scale = 1.0f;
|
||||
|
||||
[KSPField(guiName = "#LOC_ConformalDecals_gui-depth", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F2", guiUnits = "m"),
|
||||
UI_FloatRange(minValue = 0.05f, maxValue = 4f, stepIncrement = 0.05f)]
|
||||
public float depth = 1.0f;
|
||||
UI_FloatRange(stepIncrement = 0.02f)]
|
||||
public float depth = 0.2f;
|
||||
|
||||
[KSPField(guiName = "#LOC_ConformalDecals_gui-opacity", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "P0"),
|
||||
UI_FloatRange(minValue = 0.0f, maxValue = 1f, stepIncrement = 0.05f)]
|
||||
UI_FloatRange(stepIncrement = 0.05f)]
|
||||
public float opacity = 1.0f;
|
||||
|
||||
[KSPField(guiName = "#LOC_ConformalDecals_gui-cutoff", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "P0"),
|
||||
UI_FloatRange(minValue = 0.0f, maxValue = 1f, stepIncrement = 0.05f)]
|
||||
UI_FloatRange(stepIncrement = 0.05f)]
|
||||
public float cutoff = 0.5f;
|
||||
|
||||
[KSPField] public string shader = "ConformalDecals/Paint/Diffuse";
|
||||
|
||||
[KSPField] public string decalFront = string.Empty;
|
||||
[KSPField] public string decalBack = string.Empty;
|
||||
[KSPField] public string decalModel = string.Empty;
|
||||
[KSPField] public string decalProjector = string.Empty;
|
||||
[KSPField] public string decalShader = "ConformalDecals/Paint/Diffuse";
|
||||
|
||||
[KSPField] public Transform decalFrontTransform;
|
||||
[KSPField] public Transform decalBackTransform;
|
||||
@ -38,11 +39,10 @@ namespace ConformalDecals {
|
||||
[KSPField] public bool opacityAdjustable = true;
|
||||
[KSPField] public bool cutoffAdjustable = true;
|
||||
|
||||
[KSPField] public Vector2 scaleRange = new Vector2(0, 4);
|
||||
[KSPField] public Vector2 depthRange = new Vector2(0, 4);
|
||||
[KSPField] public Vector2 opacityRange = new Vector2(0, 1);
|
||||
[KSPField] public Vector2 cutoffRange = new Vector2(0, 1);
|
||||
[KSPField] public Vector2 decalQueueRange = new Vector2(2100, 2400);
|
||||
[KSPField] public Vector2 scaleRange = new Vector2(0, 4);
|
||||
[KSPField] public Vector2 depthRange = new Vector2(0, 2);
|
||||
[KSPField] public Vector2 opacityRange = new Vector2(0, 1);
|
||||
[KSPField] public Vector2 cutoffRange = new Vector2(0, 1);
|
||||
|
||||
[KSPField] public bool updateBackScale = true;
|
||||
[KSPField] public bool useBaseNormal = true;
|
||||
@ -50,7 +50,10 @@ namespace ConformalDecals {
|
||||
[KSPField] public MaterialPropertyCollection materialProperties;
|
||||
|
||||
[KSPField] public Material backMaterial;
|
||||
[KSPField] public Vector2 backTextureBaseScale;
|
||||
|
||||
private const int DecalQueueMin = 2100;
|
||||
private const int DecalQueueMax = 2400;
|
||||
private static int _decalQueueCounter = -1;
|
||||
|
||||
private List<ProjectionTarget> _targets;
|
||||
@ -58,13 +61,16 @@ namespace ConformalDecals {
|
||||
private bool _isAttached;
|
||||
private Matrix4x4 _orthoMatrix;
|
||||
private Bounds _decalBounds;
|
||||
private Vector2 _backTextureBaseScale;
|
||||
|
||||
private Material _decalMaterial;
|
||||
private Material _previewMaterial;
|
||||
|
||||
|
||||
private int DecalQueue {
|
||||
get {
|
||||
_decalQueueCounter++;
|
||||
if (_decalQueueCounter > decalQueueRange.y || _decalQueueCounter < decalQueueRange.x) {
|
||||
_decalQueueCounter = (int) decalQueueRange.x;
|
||||
if (_decalQueueCounter > DecalQueueMax || _decalQueueCounter < DecalQueueMin) {
|
||||
_decalQueueCounter = DecalQueueMin;
|
||||
}
|
||||
|
||||
return _decalQueueCounter;
|
||||
@ -74,10 +80,6 @@ namespace ConformalDecals {
|
||||
public override void OnLoad(ConfigNode node) {
|
||||
this.Log("Loading module");
|
||||
try {
|
||||
if (HighLogic.LoadedSceneIsEditor) {
|
||||
UpdateTweakables();
|
||||
}
|
||||
|
||||
// find front transform
|
||||
decalFrontTransform = part.FindModelTransform(decalFront);
|
||||
if (decalFrontTransform == null) throw new FormatException($"Could not find decalFront transform: '{decalFront}'.");
|
||||
@ -112,32 +114,25 @@ namespace ConformalDecals {
|
||||
decalProjectorTransform = part.FindModelTransform(decalProjector);
|
||||
if (decalProjectorTransform == null) throw new FormatException($"Could not find decalProjector transform: '{decalProjector}'.");
|
||||
}
|
||||
|
||||
// get back material if necessary
|
||||
if (updateBackScale) {
|
||||
this.Log("Getting material and base scale for back material");
|
||||
var backRenderer = decalBackTransform.GetComponent<MeshRenderer>();
|
||||
if (backRenderer == null) {
|
||||
this.LogError($"Specified decalBack transform {decalBack} has no renderer attached! Setting updateBackScale to false.");
|
||||
updateBackScale = false;
|
||||
}
|
||||
else {
|
||||
backMaterial = backRenderer.material;
|
||||
if (backMaterial == null) {
|
||||
this.LogError($"Specified decalBack transform {decalBack} has a renderer but no material! Setting updateBackScale to false.");
|
||||
updateBackScale = false;
|
||||
}
|
||||
else {
|
||||
_backTextureBaseScale = backMaterial.GetTextureScale(PropertyIDs._MainTex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (HighLogic.LoadedSceneIsEditor) {
|
||||
UpdateTweakables();
|
||||
}
|
||||
|
||||
// update EVERYTHING if currently attached
|
||||
if (_isAttached) {
|
||||
UpdateScale();
|
||||
UpdateTargets();
|
||||
// setup material properties
|
||||
if (HighLogic.LoadedSceneIsGame) {
|
||||
// additional load, in flight or in the editor
|
||||
materialProperties = ScriptableObject.Instantiate(materialProperties);
|
||||
}
|
||||
else {
|
||||
// first load, so get everything set up
|
||||
materialProperties = ScriptableObject.CreateInstance<MaterialPropertyCollection>();
|
||||
materialProperties.Initialize();
|
||||
}
|
||||
|
||||
// set shader
|
||||
materialProperties.SetShader(shader);
|
||||
}
|
||||
catch (Exception e) {
|
||||
this.LogException("Exception parsing partmodule", e);
|
||||
@ -147,6 +142,7 @@ namespace ConformalDecals {
|
||||
public override void OnStart(StartState state) {
|
||||
this.Log("Starting module");
|
||||
|
||||
// handle tweakables
|
||||
if (HighLogic.LoadedSceneIsEditor) {
|
||||
GameEvents.onEditorPartEvent.Add(OnEditorEvent);
|
||||
GameEvents.onVariantApplied.Add(OnVariantApplied);
|
||||
@ -154,21 +150,22 @@ namespace ConformalDecals {
|
||||
UpdateTweakables();
|
||||
}
|
||||
|
||||
// generate orthogonal projection matrix and offset it by 0.5 on x and y axes
|
||||
_orthoMatrix = Matrix4x4.identity;
|
||||
_orthoMatrix[0, 3] = 0.5f;
|
||||
_orthoMatrix[1, 3] = 0.5f;
|
||||
// clone materialProperties and setup queue
|
||||
if (HighLogic.LoadedSceneIsGame) {
|
||||
materialProperties = ScriptableObject.Instantiate(materialProperties);
|
||||
materialProperties.SetRenderQueue(DecalQueue);
|
||||
|
||||
// instantiate decal material and set uniqueish queue
|
||||
materialProperties.SetRenderQueue(DecalQueue);
|
||||
// set initial attachment state
|
||||
if (part.parent == null) {
|
||||
_isAttached = false;
|
||||
}
|
||||
else {
|
||||
OnAttach();
|
||||
}
|
||||
}
|
||||
|
||||
// set initial attachment state
|
||||
if (part.parent == null) {
|
||||
OnDetach();
|
||||
}
|
||||
else {
|
||||
OnAttach();
|
||||
}
|
||||
UpdateMaterials();
|
||||
UpdateScale();
|
||||
}
|
||||
|
||||
public void OnDestroy() {
|
||||
@ -179,25 +176,25 @@ namespace ConformalDecals {
|
||||
Camera.onPreCull -= Render;
|
||||
}
|
||||
|
||||
private void OnSizeTweakEvent(BaseField field, object obj) {
|
||||
protected void OnSizeTweakEvent(BaseField field, object obj) {
|
||||
// scale or depth values have been changed, so update scale
|
||||
// and update projection matrices if attached
|
||||
UpdateScale();
|
||||
if (_isAttached) UpdateProjection();
|
||||
}
|
||||
|
||||
private void OnMaterialTweakEvent(BaseField field, object obj) {
|
||||
protected void OnMaterialTweakEvent(BaseField field, object obj) {
|
||||
materialProperties.SetOpacity(opacity);
|
||||
materialProperties.SetCutoff(cutoff);
|
||||
}
|
||||
|
||||
private void OnVariantApplied(Part eventPart, PartVariant variant) {
|
||||
protected void OnVariantApplied(Part eventPart, PartVariant variant) {
|
||||
if (_isAttached && eventPart == part.parent) {
|
||||
UpdateTargets();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEditorEvent(ConstructionEventType eventType, Part eventPart) {
|
||||
protected void OnEditorEvent(ConstructionEventType eventType, Part eventPart) {
|
||||
if (eventPart != this.part) return;
|
||||
switch (eventType) {
|
||||
case ConstructionEventType.PartAttached:
|
||||
@ -213,7 +210,7 @@ namespace ConformalDecals {
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAttach() {
|
||||
protected void OnAttach() {
|
||||
if (part.parent == null) {
|
||||
this.LogError("Attach function called but part has no parent!");
|
||||
_isAttached = false;
|
||||
@ -224,7 +221,6 @@ namespace ConformalDecals {
|
||||
|
||||
this.Log($"Decal attached to {part.parent.partName}");
|
||||
|
||||
UpdateTargets();
|
||||
|
||||
// hide preview model
|
||||
decalFrontTransform.gameObject.SetActive(false);
|
||||
@ -233,11 +229,12 @@ namespace ConformalDecals {
|
||||
// add to preCull delegate
|
||||
Camera.onPreCull += Render;
|
||||
|
||||
UpdateScale();
|
||||
//UpdateScale();
|
||||
UpdateTargets();
|
||||
UpdateProjection();
|
||||
}
|
||||
|
||||
private void OnDetach() {
|
||||
protected void OnDetach() {
|
||||
_isAttached = false;
|
||||
|
||||
// unhide preview model
|
||||
@ -247,13 +244,19 @@ namespace ConformalDecals {
|
||||
// remove from preCull delegate
|
||||
Camera.onPreCull -= Render;
|
||||
|
||||
UpdateScale();
|
||||
//UpdateScale();
|
||||
}
|
||||
|
||||
private void UpdateScale() {
|
||||
protected void UpdateScale() {
|
||||
var aspectRatio = materialProperties.AspectRatio;
|
||||
this.Log($"Aspect ratio is {aspectRatio}");
|
||||
var size = new Vector2(scale, scale * materialProperties.AspectRatio);
|
||||
|
||||
// update orthogonal matrix scale
|
||||
_orthoMatrix = Matrix4x4.identity;
|
||||
_orthoMatrix[0, 3] = 0.5f;
|
||||
_orthoMatrix[1, 3] = 0.5f;
|
||||
|
||||
_orthoMatrix[0, 0] = 1 / size.x;
|
||||
_orthoMatrix[1, 1] = 1 / size.y;
|
||||
_orthoMatrix[2, 2] = 1 / depth;
|
||||
@ -262,28 +265,67 @@ namespace ConformalDecals {
|
||||
_decalBounds.center = Vector3.forward * (depth / 2);
|
||||
_decalBounds.extents = new Vector3(size.x / 2, size.y / 2, depth / 2);
|
||||
|
||||
if (decalModelTransform == null) {
|
||||
this.LogError("decalModelTransform is null!");
|
||||
}
|
||||
|
||||
// rescale preview model
|
||||
decalModelTransform.localScale = new Vector3(size.x, size.y, (size.x + size.y) / 2);
|
||||
|
||||
// update back material scale
|
||||
if (updateBackScale) {
|
||||
backMaterial.SetTextureScale(PropertyIDs._MainTex, new Vector2(size.x * _backTextureBaseScale.x, size.y * _backTextureBaseScale.y));
|
||||
backMaterial.SetTextureScale(PropertyIDs._MainTex, new Vector2(size.x * backTextureBaseScale.x, size.y * backTextureBaseScale.y));
|
||||
}
|
||||
|
||||
// update material scale
|
||||
materialProperties.SetScale(size);
|
||||
}
|
||||
|
||||
private void UpdateProjection() {
|
||||
protected void UpdateMaterials() {
|
||||
materialProperties.UpdateMaterials();
|
||||
_decalMaterial = materialProperties.DecalMaterial;
|
||||
_previewMaterial = materialProperties.PreviewMaterial;
|
||||
|
||||
// get back material if necessary
|
||||
if (updateBackScale) {
|
||||
this.Log("Getting material and base scale for back material");
|
||||
var backRenderer = decalBackTransform.GetComponent<MeshRenderer>();
|
||||
if (backRenderer == null) {
|
||||
this.LogError($"Specified decalBack transform {decalBack} has no renderer attached! Setting updateBackScale to false.");
|
||||
updateBackScale = false;
|
||||
}
|
||||
else {
|
||||
backMaterial = backRenderer.material;
|
||||
if (backMaterial == null) {
|
||||
this.LogError($"Specified decalBack transform {decalBack} has a renderer but no material! Setting updateBackScale to false.");
|
||||
updateBackScale = false;
|
||||
}
|
||||
else {
|
||||
if (backTextureBaseScale == default) backTextureBaseScale = backMaterial.GetTextureScale(PropertyIDs._MainTex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (decalFrontTransform == null) {
|
||||
this.LogError("No reference to decal front transform");
|
||||
return;
|
||||
}
|
||||
|
||||
decalFrontTransform.GetComponent<MeshRenderer>().material = _previewMaterial;
|
||||
}
|
||||
|
||||
protected void UpdateProjection() {
|
||||
if (!_isAttached) return;
|
||||
|
||||
var bounds = new OrientedBounds(decalProjectorTransform.localToWorldMatrix, _decalBounds);
|
||||
|
||||
// project to each target object
|
||||
foreach (var target in _targets) {
|
||||
target.Project(_orthoMatrix, new OrientedBounds(decalProjectorTransform.localToWorldMatrix, _decalBounds), decalProjectorTransform);
|
||||
target.Project(_orthoMatrix, bounds, decalProjectorTransform, useBaseNormal);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTargets() {
|
||||
protected void UpdateTargets() {
|
||||
if (_targets == null) {
|
||||
_targets = new List<ProjectionTarget>();
|
||||
}
|
||||
@ -319,7 +361,7 @@ namespace ConformalDecals {
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTweakables() {
|
||||
protected void UpdateTweakables() {
|
||||
// setup tweakable fields
|
||||
var scaleField = Fields[nameof(scale)];
|
||||
var depthField = Fields[nameof(depth)];
|
||||
@ -369,12 +411,12 @@ namespace ConformalDecals {
|
||||
}
|
||||
}
|
||||
|
||||
private void Render(Camera camera) {
|
||||
protected void Render(Camera camera) {
|
||||
if (!_isAttached) return;
|
||||
|
||||
// render on each target object
|
||||
foreach (var target in _targets) {
|
||||
target.Render(materialProperties.DecalMaterial, part.mpb, camera);
|
||||
target.Render(_decalMaterial, part.mpb, camera);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using ConformalDecals.MaterialModifiers;
|
||||
using ConformalDecals.Util;
|
||||
using UnityEngine;
|
||||
@ -7,29 +6,35 @@ namespace ConformalDecals {
|
||||
public class ModuleConformalDecalFlag : ModuleConformalDecalBase {
|
||||
[KSPField] public MaterialTextureProperty flagTextureProperty;
|
||||
|
||||
private const string defaultFlag = "Squad/Flags/default";
|
||||
|
||||
public override void OnLoad(ConfigNode node) {
|
||||
|
||||
if (materialProperties == null) {
|
||||
// materialProperties is null, so make a new one
|
||||
materialProperties = ScriptableObject.CreateInstance<MaterialPropertyCollection>();
|
||||
materialProperties.Initialize();
|
||||
}
|
||||
else {
|
||||
// materialProperties already exists, so make a copy
|
||||
materialProperties = ScriptableObject.Instantiate(materialProperties);
|
||||
}
|
||||
|
||||
// set shader
|
||||
materialProperties.SetShader(decalShader);
|
||||
|
||||
base.OnLoad(node);
|
||||
|
||||
|
||||
if (HighLogic.LoadedSceneIsGame) {
|
||||
UpdateMaterials();
|
||||
UpdateScale();
|
||||
UpdateProjection();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnStart(StartState state) {
|
||||
base.OnStart(state);
|
||||
|
||||
UpdateFlag(EditorLogic.FlagURL != string.Empty ? EditorLogic.FlagURL : HighLogic.CurrentGame.flagURL);
|
||||
GameEvents.onMissionFlagSelect.Add(UpdateFlag);
|
||||
if (HighLogic.LoadedSceneIsGame) {
|
||||
UpdateFlag(EditorLogic.FlagURL != string.Empty ? EditorLogic.FlagURL : HighLogic.CurrentGame.flagURL);
|
||||
GameEvents.onMissionFlagSelect.Add(UpdateFlag);
|
||||
}
|
||||
else {
|
||||
UpdateFlag(defaultFlag);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnIconCreate() {
|
||||
this.Log("called OnIconCreate");
|
||||
OnStart(StartState.None);
|
||||
UpdateScale();
|
||||
}
|
||||
|
||||
private void UpdateFlag(string flagUrl) {
|
||||
@ -42,14 +47,17 @@ namespace ConformalDecals {
|
||||
|
||||
if (flagTextureProperty == null) {
|
||||
this.Log("Initializing flag property");
|
||||
flagTextureProperty = new MaterialTextureProperty("_Decal", flagTexture, isMain: true);
|
||||
flagTextureProperty = ScriptableObject.CreateInstance<MaterialTextureProperty>();
|
||||
flagTextureProperty.Name = "_Decal";
|
||||
flagTextureProperty.isMain = true;
|
||||
materialProperties.AddProperty(flagTextureProperty);
|
||||
}
|
||||
else {
|
||||
flagTextureProperty.texture = flagTexture;
|
||||
}
|
||||
else { }
|
||||
|
||||
materialProperties.UpdateMaterials();
|
||||
flagTextureProperty.texture = flagTexture;
|
||||
|
||||
|
||||
UpdateMaterials();
|
||||
}
|
||||
}
|
||||
}
|
@ -5,35 +5,42 @@ using UnityEngine;
|
||||
namespace ConformalDecals {
|
||||
public class ModuleConformalDecalGeneric : ModuleConformalDecalBase {
|
||||
public override void OnLoad(ConfigNode node) {
|
||||
|
||||
if (materialProperties == null) {
|
||||
// materialProperties is null, so make a new one
|
||||
materialProperties = ScriptableObject.CreateInstance<MaterialPropertyCollection>();
|
||||
materialProperties.Initialize();
|
||||
}
|
||||
else {
|
||||
// materialProperties already exists, so make a copy
|
||||
materialProperties = ScriptableObject.Instantiate(materialProperties);
|
||||
}
|
||||
base.OnLoad(node);
|
||||
|
||||
// set shader
|
||||
materialProperties.SetShader(decalShader);
|
||||
materialProperties.SetShader(shader);
|
||||
// add texture nodes
|
||||
foreach (var textureNode in node.GetNodes("TEXTURE")) {
|
||||
materialProperties.AddProperty(new MaterialTextureProperty(textureNode));
|
||||
var textureProperty = ScriptableObject.CreateInstance<MaterialTextureProperty>();
|
||||
textureProperty.ParseNode(textureNode);
|
||||
materialProperties.AddProperty(textureProperty);
|
||||
}
|
||||
|
||||
// add float nodes
|
||||
foreach (var floatNode in node.GetNodes("FLOAT")) {
|
||||
materialProperties.AddProperty(new MaterialFloatProperty(floatNode));
|
||||
var floatProperty = ScriptableObject.CreateInstance<MaterialFloatProperty>();
|
||||
floatProperty.ParseNode(floatNode);
|
||||
materialProperties.AddProperty(floatProperty);
|
||||
}
|
||||
|
||||
// add color nodes
|
||||
foreach (var colorNode in node.GetNodes("COLOR")) {
|
||||
materialProperties.AddProperty(new MaterialColorProperty(colorNode));
|
||||
var colorProperty = ScriptableObject.CreateInstance<MaterialColorProperty>();
|
||||
colorProperty.ParseNode(colorNode);
|
||||
materialProperties.AddProperty(colorProperty);
|
||||
}
|
||||
|
||||
base.OnLoad(node);
|
||||
if (HighLogic.LoadedSceneIsGame) {
|
||||
UpdateMaterials();
|
||||
UpdateScale();
|
||||
UpdateProjection();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnIconCreate() {
|
||||
this.Log("called OnIconCreate");
|
||||
OnStart(StartState.None);
|
||||
UpdateScale();
|
||||
}
|
||||
}
|
||||
}
|
@ -17,36 +17,23 @@ namespace ConformalDecals {
|
||||
|
||||
// property block
|
||||
private readonly MaterialPropertyBlock _decalMPB;
|
||||
|
||||
private static readonly int normalID = Shader.PropertyToID("_BumpMap");
|
||||
private static readonly int normalIDST = Shader.PropertyToID("_BumpMap_ST");
|
||||
|
||||
private static readonly int normalID = Shader.PropertyToID("_BumpMap");
|
||||
private static readonly int normalIDST = Shader.PropertyToID("_BumpMap_ST");
|
||||
|
||||
public ProjectionTarget(MeshRenderer targetRenderer, Mesh targetMesh, bool useBaseNormal) {
|
||||
target = targetRenderer.transform;
|
||||
_targetRenderer = targetRenderer;
|
||||
_targetMesh = targetMesh;
|
||||
var targetMaterial = targetRenderer.sharedMaterial;
|
||||
|
||||
_decalMPB = new MaterialPropertyBlock();
|
||||
|
||||
if (useBaseNormal && targetMaterial.HasProperty(normalID)) {
|
||||
var normal = targetMaterial.GetTexture(normalID);
|
||||
if (normal != null) {
|
||||
|
||||
_decalMPB.SetTexture(normalID, targetMaterial.GetTexture(normalID));
|
||||
|
||||
var normalScale = targetMaterial.GetTextureScale(normalID);
|
||||
var normalOffset = targetMaterial.GetTextureOffset(normalID);
|
||||
|
||||
_decalMPB.SetVector(normalIDST, new Vector4(normalScale.x, normalScale.y, normalOffset.x, normalOffset.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Project(Matrix4x4 orthoMatrix, OrientedBounds projectorBounds, Transform projector) {
|
||||
public void Project(Matrix4x4 orthoMatrix, OrientedBounds projectorBounds, Transform projector, bool useBaseNormal) {
|
||||
var targetBounds = _targetRenderer.bounds;
|
||||
if (projectorBounds.Intersects(targetBounds)) {
|
||||
_projectionEnabled = true;
|
||||
|
||||
var targetMaterial = _targetRenderer.sharedMaterial;
|
||||
var projectorToTargetMatrix = target.worldToLocalMatrix * projector.localToWorldMatrix;
|
||||
|
||||
var projectionMatrix = orthoMatrix * projectorToTargetMatrix.inverse;
|
||||
@ -57,6 +44,19 @@ namespace ConformalDecals {
|
||||
_decalMPB.SetVector(_decalNormalID, decalNormal);
|
||||
_decalMPB.SetVector(_decalTangentID, decalTangent);
|
||||
Debug.Log($"Projection enabled for {target.gameObject}");
|
||||
|
||||
if (useBaseNormal && targetMaterial.HasProperty(normalID)) {
|
||||
var normal = targetMaterial.GetTexture(normalID);
|
||||
if (normal != null) {
|
||||
|
||||
_decalMPB.SetTexture(normalID, targetMaterial.GetTexture(normalID));
|
||||
|
||||
var normalScale = targetMaterial.GetTextureScale(normalID);
|
||||
var normalOffset = targetMaterial.GetTextureOffset(normalID);
|
||||
|
||||
_decalMPB.SetVector(normalIDST, new Vector4(normalScale.x, normalScale.y, normalOffset.x, normalOffset.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
_projectionEnabled = false;
|
||||
|
Loading…
Reference in New Issue
Block a user