I have used a shader that is very heavy for mobile performance. Can someone help me to improve it in order to get better performance?
I have noticed that my FPS with this shader goes from 60 to 30.
Shader "Custom/Sphered2"
{Properties
{
[HDR] _Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_ColorStrength("Color Strenth", Range(1,4)) = 1
_EmissionColor ("_EmissionColor Color", Color) = (1,1,1,1)
_EmissionTex ("_EmissionColor (RGB)", 2D) = "white" {}
_EmissionStrength("_EmissionColor Strenth", Range(0,4)) = 1
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
// _position ("World Position", Vector) = (0,0,0,0)
// _Radius ("Sphere Radius", Range(0,100)) = 0
//_Softness("Sphere Softness", Range(0,100)) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex,_EmissionTex;
struct Input
{
float2 uv_MainTex;
float2 uv_EmissionTex;
float3 worldPos;
};
half _Glossiness;
half _Metallic;
fixed4 _Color,_EmissionColor;
half _ColorStrength,_EmissionStrength;
uniform float4 GLOBALmask_position2;
uniform half GLOBALmask_Radius2;
uniform half GLOBALmask_Softness;
// 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)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
half grayscale = (c.r + c.g + c.b) * 0.333;
fixed3 cgg = fixed3(grayscale,grayscale,grayscale);
fixed4 e = tex2D (_EmissionTex, IN.uv_EmissionTex) * _EmissionColor *_EmissionStrength;
half d = distance(GLOBALmask_position2,IN.worldPos);
half sum = saturate((d - GLOBALmask_Radius2)/ -GLOBALmask_Softness);
fixed4 lerpColor = lerp(fixed4(cgg,1),c * _ColorStrength,sum);
fixed4 lerpEmission = lerp(fixed4(0,0,0,0),e,sum);
o.Albedo =c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Emission = lerpEmission.rgb;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
I have used it like this :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RayCastMovePos : MonoBehaviour
{
public Transform playerTransform;
public float radius2,sm;
public Vector4 myPos2;
void Update()
{
myPos2= new Vector4 ( playerTransform.position.x ,
playerTransform.position.y, playerTransform.position.z, 0);
//radius =Mathf .Clamp ( ( myVisualizer.allRythem
[0]+myVisualizer.allRythem [1]+myVisualizer.allRythem [2]) * 170,2,1000);
// radius2 =Mathf .Clamp ( ( myVisualizer.allRythem
[3]+myVisualizer.allRythem [4]+myVisualizer.allRythem [5]) * 150,2,1000);
Shader.SetGlobalVector ("GLOBALmask_position2", myPos2);
Shader.SetGlobalFloat ("GLOBALmask_Radius2", radius2);
Shader.SetGlobalFloat ("GLOBALmask_Softness", sm );
}
}
I am new to shaders, but if there are any suggestions for glowing a sprite, I would be glad to hear it.
If this is for a sprite, then do you really need to use a surface shader? These include tons of overhead, like lightmapping support, shadow casting/receiving, forward light support, etc. I'm sure a vertex/fragment shader would work fine for your purposes. You get emission by simply adding extra color to the final output.
Here is how the body of Unity's sprite shader looks:
https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/CGIncludes/UnitySprites.cginc
Related
I'm trying to implement a simulation of an ocean based on this tutorial but I can't get my shader to affect my plane. It stays completly flat whatever I do.
This is my shader :
Shader "Custom/Waves"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_NormalMap ("Normal Map", 2D) = "bump" {}
//Wave Properties
_Direction("Direction", Vector) = (1.0, 0.0, 0.0, 1.0)
_Steepness("Steepness", Range(0.1,1.0)) = 0.5
_Freq("Frequency", Range(1.0,10.0)) = 1.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
float _Steepness, _Freq;
float4 _Direction;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// 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 vert(inout appdata_full v){
float3 pos = v.vertex.xyz;
float4 dir = normalize(_Direction);
float defaultWavelength = 2 * UNITY_PI;
float wL = defaultWavelength / _Freq;
float phase = sqrt(9.8/wL);
float disp = wL * (dot(dir, pos) - (phase * _Time.y));
float peak = _Steepness/wL;
pos.x += dir.x * (peak * cos(disp));
pos.y = peak * sin(disp);
pos.z += dir.y * (peak * cos(disp));
v.vertex.xyz = pos;
}
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
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;
}
ENDCG
}
FallBack "Diffuse"
}
I thought that it might be the link between the plane, the material and the shader but it doesn't seem to help. I don't have any idea of what I did wrong. I tried with and without GPU instancing and it does not change anything.
You forgot to declare that you want to use a vertex function.
Add this before or after the other pragma
#pragma vertex vert
I'm making a 2D mobile game but I want to use 3D objects in shop section. So, in the shop section, I have a scroll rect and a viewport. I can scroll and the mask component works as expected with 2D objects. But when I add 3D objects, the objects getting out of the mask. I researched the forums and I find a custom shader. When I apply the shader to the objects materials, it partially works. But the depth or shadows are not working properly. I know not much about shaders. You can take a look at this Image. Box on the right is the original one, box on the left is the one with custom shader.
My shader code is here;
Shader "Custom/NewSurfaceShader" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_StencilComp("Stencil Comparison", Float) = 8
_Stencil("Stencil ID", Float) = 0
_StencilOp("Stencil Operation", Float) = 0
_StencilWriteMask("Stencil Write Mask", Float) = 255
_StencilReadMask("Stencil Read Mask", Float) = 255
_ColorMask("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags { "RenderType"="UI""Queue"="Transparent" }
LOD 200
ZTest[unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask[_ColorMask]
Stencil
{
Ref 1
Comp LEqual
Pass Keep
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
CGPROGRAM
#pragma surface surf Standard vertex:vert fullforwardshadows
#pragma target 3.0
#include "UnityUI.cginc"
struct Input
{
float2 uv_MainTex;
float4 worldPosition;
};
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
o.worldPosition = v.vertex;
}
sampler2D _MainTex;
half _Glossiness;
half _Metallic;
fixed4 _Color;
float4 _ClipRect;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
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;
o.Alpha *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#ifdef UNITY_UI_ALPHACLIP
clip(o.Alpha - 0.001);
#endif
}
ENDCG
}
FallBack "Diffuse"
}
I am trying to make two different objects with the same size of texture / same material, which should be repeating; Without making new material for every new object I create. Below is an example of what I am trying to achieve.
Material A on both objects should look the same, the cube on the right represents how it should look.
This is fixed and working!
I had to make a Unity shader, which uses world space instead of local space (default). This is the code of a shader I used:
Shader "Legacy Shaders/Diffuse - Worldspace" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_Scale("Texture Scale", Float) = 1.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
fixed4 _Color;
float _Scale;
struct Input {
float3 worldNormal;
float3 worldPos;
};
void surf (Input IN, inout SurfaceOutput o) {
float2 UV;
fixed4 c;
if (abs(IN.worldNormal.x) > 0.5) {
UV = IN.worldPos.yz; // side
c = tex2D(_MainTex, UV* _Scale); // use WALLSIDE texture
}
else if (abs(IN.worldNormal.z) > 0.5) {
UV = IN.worldPos.xy; // front
c = tex2D(_MainTex, UV* _Scale); // use WALL texture
}
else {
UV = IN.worldPos.xz; // top
c = tex2D(_MainTex, UV* _Scale); // use FLR texture
}
o.Albedo = c.rgb * _Color;
}
ENDCG
}
Fallback "Legacy Shaders/VertexLit"
}
Fixed version:
Fixed
Sources of Knowledge I used:
Video tutorial by PushyPixels
Blocks of code taken from this blog
#derHugo set me on the right track, thank you!!
How can a Custom Standard Surface Shader be used to animate a value towards a target value?
For Example:
...
float targetAlpha; //Set by the property block, or a C# script
float currrentAlpha; //Used internally only.
void surf (Input IN, inout SurfaceOutputStandard o)
{
currrentAlpha = lerp(currrentAlpha, targetAlpha, unity_DeltaTime.x);
o.Alpha = currrentAlpha;
}
This code does not work but should demonstrate what the goal is: when targetAlpha is set, the shader will fade towards that value.
There are few ways this can be done. One of them is using built-in shader variables:
Shader "Custom/Test" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_TargetAlpha ("TargetAlpha", Range(0, 1)) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
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;
struct Input {
float2 uv_MainTex;
};
half _Alpha;
fixed4 _Color;
half _TargetAlpha;
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = lerp(o.Alpha, _TargetAlpha, clamp(_SinTime.w, 0, 1));
}
ENDCG
}
FallBack "Diffuse"
}
The shader in the answer above still works in Unity 2018.2. However, _SinTime oscillates between -1 and 1, while we want the range to be between 0 and 1. The code clamp(_SinTime.w, 0, 1) clamps onto the desired values, however the alpha stays at zero too long. So we need the absolute value, like so: abs(_SinTime.w).
The modified shader:
Shader "Custom/Test" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_TargetAlpha ("TargetAlpha", Range(0, 1)) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
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;
struct Input {
float2 uv_MainTex;
};
half _Alpha;
fixed4 _Color;
half _TargetAlpha;
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = lerp(o.Alpha, _TargetAlpha, abs(_SinTime.w));
}
ENDCG
}
FallBack "Diffuse"
}
I'm very new to Shaders programming, I was trying to create a shader which:
Allows to change 2 textures with 2 corresponding normal maps (fade in/fade out)
Doublesided (show mesh from both sides of the surface)
Here is what I end up with:
Shader "Custom/TextureBlend" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_Blend ("Texture Blend", Range(0,1)) = 0.0
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_MainTex2 ("Albedo 2 (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_BumpMap ("Bumpmap", 2D) = "bump" {}
_BumpMap2 ("Bumpmap", 2D) = "bump" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Cull Off
ZTest LEqual
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
sampler2D _MainTex2;
sampler2D _BumpMap;
sampler2D _BumpMap2;
struct Input {
float2 uv_MainTex;
float2 uv_MainTex2;
float2 uv_BumpMap;
float2 uv_BumpMap2;
};
half _Blend;
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = lerp (tex2D (_MainTex, IN.uv_MainTex), tex2D (_MainTex2, IN.uv_MainTex2), _Blend) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
fixed4 n = lerp (tex2D (_BumpMap, IN.uv_BumpMap), tex2D (_BumpMap2, IN.uv_BumpMap2), _Blend) * _Color;
o.Normal = n.rgb;
}
ENDCG
}
FallBack "Diffuse"
}
It works but for some reason the texture on the surface looks dim (on the other side of the mesh which usually invisible it's even darker), and normal map reflections barely visible.
Here, on the left you can see the plane with my shader, on the right - standard shader:
Also the reflection looks really strange, if I will move Metallic slider to the right you will see it:
Normal maps store vector information while regular textures are unsigned, so you need to use the UnpackNormal() helper method as shown in the samples. You also don't need to multiply by Color.
final code would then be along the lines of:
fixed4 n0 = tex2D(_BumpMap, IN.uv_BumpMap);
fixed4 n1 = tex2D(_BumpMap2, IN.uv_BumpMap2);
o.Normal = UnpackNormal(lerp(n0, n1, _Blend)).xyz;