Unity Surface Shader Texture Moving When Object Moves - unity3d

In Unity I have modified a cube surface shader that works properly while the associated object is stationary, but when the object is moved the texture is moved on the object. I would like the texture to not move if the object moves or ideally even if vertices of the object are moved around at runtime. This is a gif created during runtime of what happens when the object is stationary vs moving:
GiphyLink
This is the shader code I've been working with (this is the code used in the gif that I linked above):
"CShader" {
Properties{
_CubeMap("Cube Map", Cube) = "white" {}
_CubeMap2("Cube Map 2", Cube) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Color3("Color 1", Color) = (1,1,1,1)
_Color4("Color 2", Color) = (1,1,1,1)
_Blend("Texture Blend", Range(0,1)) = 0.0
_Glossiness("Smoothness", Range(0,1)) = 0.0
_Metallic("Metallic", Range(0,1)) = 0.0
}
SubShader{
Tags { "RenderType" = "Fade" }
CGPROGRAM
#pragma target 4.5
#pragma surface surf Standard alpha:fade vertex:vert
struct Input {
float2 uv_CubeMap;
float3 customColor;
};
fixed4 _Color3;
fixed4 _Color4;
half _Blend;
half _Glossiness;
half _Metallic;
samplerCUBE _CubeMap;
samplerCUBE _CubeMap2;
void vert(inout appdata_full v, out Input oo) {
UNITY_INITIALIZE_OUTPUT(Input, oo);
oo.customColor = v.vertex.xyz;
}
void surf(Input INN, inout SurfaceOutputStandard oo) {
fixed4 d = texCUBE(_CubeMap2, INN.customColor) * _Color3;
d = lerp(d, texCUBE(_CubeMap, INN.customColor) * _Color4, 1 / (1 + exp(100 * (-(INN.uv_CubeMap.y)))));
oo.Albedo = d.rgb;
oo.Metallic = _Metallic;
oo.Smoothness = _Glossiness;
oo.Alpha = d.a;
}
ENDCG
}
Fallback "Diffuse"
I've tried many things including setting vertices in c# script and passing them to the shader but nothing has worked so far likely because I've coded it wrong or had the wrong procedure.
Any help would be greatly appreciated, Thank you.

Related

How to tile texture with MixedRealityToolkit shader and Round Corners?

I'm trying to make an animated material with the MRTK in Unity. The goal is to make an effect with look like starting with a circle and propagating the texture to rest of the plane.
For now I use the MixedRealityToolkit standard shader and use the round corner option. With an animation I made that :
My problem is that I can't tile the texture to reduce the size of the texture and repeat it. Also for non-square object, the texture is stretched and it's not really nice.
If I try to change the tile setting, the texture is not repeated (texture is well in "Repeat Mode", it works when I untick Round Corners option)
(If I display Unity selection outline, I obtained the repeated texture, but it's not displayed ... )
Does anyone have a good idea to do that with the MRTK shaders or how to write a specific shader for this effect ?
I found a solution, writing my own shader :
Shader "Custom/testShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_ForegroundMask("Foreground Mask", 2D) = "white" {}
_RadiusSize("Radius size", Range(0,2)) = 0
_BorderWidth("Smooth Edge width", Range(0,1)) = 0.5
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags {"Queue"="Transparent" "RenderType"="Transparent" }
LOD 200
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows alpha:fade
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
sampler2D _ForegroundMask;
struct Input
{
float2 uv_MainTex;
float2 uv_ForegroundMask;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
float _RadiusSize;
float _BorderWidth;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed2 dist;
dist.x = IN.uv_ForegroundMask.x - 0.5;
dist.y = IN.uv_ForegroundMask.y - 0.5;
fixed circle= 1.0 - smoothstep(_RadiusSize-(_RadiusSize * _BorderWidth),_RadiusSize+(_RadiusSize * _BorderWidth), dot(dist,dist)*4.0);
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a * circle;
}
ENDCG
}
FallBack "Diffuse"
}

Gradient shader Z fighting in Scene view only

I have created the following gradient that takes an Image components source image and apply a two colour gradient to it. Using a toggle it can be switched to using the Source image's alpha for the gradient alpha, or set the alpha per gradient colour.
Properties
{
[PerRendererData] _MainTex ("Texture", 2D) = "white" {}
[Header(Colours)]
_Color1("Color 1", Color) = (0,0,0,1)
_Color2("Color 2", Color) = (1,1,1,1)
[Toggle]_UseImageAlpha("Use Image alpha", float) = 0
[Header(Cull mode)]
[Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull mode", float) = 2
[Header(ZTest)]
[Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", float) = 4
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 1
}
SubShader
{
Tags {"Queue" = "Transparent" "RenderType"="Transparent"}
LOD 100
Blend SrcAlpha OneMinusSrcAlpha
ZTest [_ZTest]
Cull [_CullMode]
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_local _ UNITY_UI_ALPHACLIP
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
fixed4 col : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
fixed4 col : COLOR;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color1;
fixed4 _Color2;
bool _UseImageAlpha;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.col = v.col;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
if (_UseImageAlpha) {
_Color1.a = i.col.a;
_Color2.a = i.col.a;
}
fixed4 col = tex2D(_MainTex, i.uv);
col *= lerp(_Color1, _Color2, i.uv.y);
col.a = clamp(col.a, 0, 1);
#ifdef UNITY_UI_ALPHACLIP
clip(col.a - .001);
#endif
return col;
}
ENDCG
}
}
This shader works fine and shows the gradient as expected, however once I start adding multiple layers of Images (in example a blue square behind it, and a green quare in front of it) it starts having issues with Z fighting in the scene view only based on the angle of the scene camera with the object that comes next in the hierachy (in this example the green square). In the Game view and on builds the Z fighting doesn't occur.
I am using the default LessEqual ZTest option, with back culling and render queue set to 3000 (which is the same as the render queue for the image in front and behind of it). As per Unity's documentation having it set to LessEqual should make it so Objects in front get drawn on top, and objects behind get hidden:
How should depth testing be performed. Default is LEqual (draw objects in from or at the distance as existing objects; hide objects behind them).
Setting the ZTest to any of the other options (off, always, greaterEqual etc) doens't yield a better result.
If I set the Render queue higher (3001) it will always draw the gradient on top in the Scene view (no changes in the Game view) whereas setting it to 2999 will still make it z fight with the object in front of it (green square), while making the blue square behind it transparent.
When I only have the green square in front of the gradient it will z fight in some places, while cutting out the green square in other places where the source image doesn't have any pixels.
Using the alpha of the source image, or using the alpha of the two individual colours does not make a difference either.
(gyazo) Example gif of the fighting changing depending on the camera angle.
What is causing this z fighting, and why does it only occur in the scene view?
Using Unity 2019.3.13f1, same results in 2019.2, 2019.1m 2018.4 LTS, 2017 LTS on Windows.
Try adding ZWrite Off. With shaders it might be useful just to start with (or at least look at) one of Unity's built-in shaders that is close to what you want. In your case that would be UI-Default.shader.

render only some parts of the texture Unity

as the title described i want to render only some parts of the texture. For example i have an 1024*1024 texture and now i want to render the area(square) that's between the points 0/0 50/50 pixel and the area 600/600 1024/1024.
Is something like that possible?
Maybe you can help me with some logic steps that i need to go, because i don't really know how to start.
Yeah i need an shader with 2 texture slots and a scripts that renders only some parts^^
I think it has something to do with this here: https://answers.unity.com/questions/529814/how-to-have-2-different-objects-at-the-same-place.html
The following basic surface shader "removes" all pixels outside between 50/50 and 600/600 (this is called clipping):
Shader "Custom/ClippedTexture" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
float4 _MainTex_TexelSize;
void surf (Input IN, inout SurfaceOutput o) {
float u = IN.uv_MainTex.x * _MainTex_TexelSize.x;
float v = IN.uv_MainTex.y * _MainTex_TexelSize.y;
if((u < 51 && v < 51) || (u > 599 && v > 599)) {
clip(-1); // skip pixel
} else {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
}
ENDCG
}
Fallback "Diffuse"
}
You can save this Shader into the Shader directory of your project and create a material that uses it. Hope this helps.

Extending the Unity Standard shader with an additional subshader

I'm applying a "burning" dissolve shader to an object which uses the Standard shader already. Because I need the Standard shader for better lighting, etc, I looked into how to use them "both" or how to extend the standard shader.
According to the Unity docs I can define which lighting mode I want to use in the pragma so I used Standard. That must not work the way I thought, because I see none of the lighting I do when using the standard shader directly.
I'm using the burning dissolve shader from Harry Alisavakis
Shader "Custom/BurnDissolve" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_SliceGuide("Slice Guide (RGB)", 2D) = "white" {}
_SliceAmount("Slice Amount", Range(0.0, 1.0)) = 0
_BurnSize("Burn Size", Range(0.0, 1.0)) = 0.15
_BurnRamp("Burn Ramp (RGB)", 2D) = "white" {}
_BurnColor("Burn Color", Color) = (1,1,1,1)
_EmissionAmount("Emission amount", float) = 2.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Cull Off
CGPROGRAM
#pragma surface surf Standard
fixed4 _Color;
sampler2D _MainTex;
sampler2D _SliceGuide;
sampler2D _BumpMap;
sampler2D _BurnRamp;
fixed4 _BurnColor;
float _BurnSize;
float _SliceAmount;
float _EmissionAmount;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutputStandard o) {
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
half test = tex2D(_SliceGuide, IN.uv_MainTex).rgb - _SliceAmount;
clip(test);
if (test < _BurnSize && _SliceAmount > 0) {
o.Emission = tex2D(_BurnRamp, float2(test * (1 / _BurnSize), 0)) * _BurnColor * _EmissionAmount;
}
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Standard"
}
I also tried adding this as another subshader to a copy of the Standard shader source, but I wasn't able to get it working there. If I put it before the others, it works as if it was alone, if I put it after, the standard shader works like if it was alone.
I'm still new to shaders so I'm sure I'm misunderstanding this. How can I get the dissolve shader to apply as well the standard shader, without hopefully having to manually rewrite stuff.
Per request, here are the images I'm using (which were originally provided by the linked dissolve shader article).
As _SliceGuide:
As _BurnRamp:
Using the #prama target 3.0 and o.Smoothness = 0.5f changes Shaman mentioned, I get this:
Which is definitely better, but I guess there are effects Standard is giving me because here's how Standard by itself looks:
Standard shader uses shader model 3.0 target, to get nicer looking lighting.
So you need add this: #pragma target 3.0.
Also Standard shader's default config has its smoothness set to 0.5 whereas in your shader's case it's set to 0, so in order to make the shaders match in terms of lighting, you have to add following line: o.Smoothness = 0.5f;.

Fluctuate float value in an Unity shader

I'm trying to fluctuate between two values inside a shader to achieve a glowing effect.
I need it to be done inside the shader itself and not via C# scripting.
I've tried using the _Time value that Unity gives us for shader animation but it isn't working:
Shader "Test shader" {
Properties {
_ColorTint ("Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_GlowColor("Glow Color", Color) = (1,0,0,1)
_GlowPower("Glow Power", Float) = 3.0
_UpDown("Shine Emitter Don't Change", Float) = 0
}
SubShader {
Tags {
"RenderType"="Opaque"
}
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float4 color : Color;
float2 uv_MainTex;
float3 viewDir;
float4 _Time;
};
float4 _ColorTint;
sampler2D _MainTex;
float4 _GlowColor;
float _GlowPower;
float _UpDown;
void surf(Input IN, inout SurfaceOutput o) {
if (_UpDown == 0) {
_GlowPower += _Time.y;
}
if (_UpDown == 1) {
_GlowPower -= _Time.y;
}
if (_GlowPower <= 1) {
_UpDown = 0;
}
if (_GlowPower >= 3) {
_UpDown = 1;
}
IN.color = _ColorTint;
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * IN.color;
half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
o.Emission = _GlowColor.rgb * pow(rim, _GlowPower);
}
ENDCG
}
FallBack "Diffuse"
}
This makes the glow grow to the infinite.
What am I doing wrong?
Extending my comment slightly:
You can't use _Time.y in this case, as it is the elapsed time since the game started, thus it will increase over time.
You can use _SinTime.y instead, which represents sin(_Time.y). This means that oscillates between the values -1 and 1. You can use this and assign (maybe a scaled version of _SinTime) to your variable: _GlowPower = C * _SinTime.y
More on build-in shader variables: http://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
For doing a pulsing glow... I'd have a script 'outside' the shader and send in a paramater (_GlowPower) calculate in c# script like this....
glowPow = Mathf.Sin(time);
Then you only need to calculate it once. IF you put it in VErtex shader... it does it once per vertex, and if its in surface shader... then once per pixel = performance waste.
you can send variables to your shader like this... (very handy)
material.SetFloat(propertyName, valueToSend);
So you could send, time, strength, glow or whatverer you want.
If you really need to do a glow calculation per vertex or per pixel, then use
_glowPow = sin(_time);
inside the shader.