Ok Im trying to do a standard blur material like this (the darkened beat saber menu)
But on a 3D object, so not a camera effect or canvas material. I found some assets that provide a low quality blur but I need it glossy, and a nice Gaussian blur. The one I have has weird streaks:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,)' with 'UnityObjectToClipPos()'
Shader "Custom/WaterBlur" {
Properties {
_blurSizeXY("BlurSizeXY", Range(0,10)) = 0
}
SubShader {
// Draw ourselves after all opaque geometry
Tags { "Queue" = "Transparent" }
// Grab the screen behind the object into _GrabTexture
GrabPass { }
// Render the object with the texture generated above
Pass {
CGPROGRAM
#pragma debug
#pragma vertex vert
#pragma fragment frag
#ifndef SHADER_API_D3D11
#pragma target 3.0
#else
#pragma target 4.0
#endif
sampler2D _GrabTexture : register(s0);
float _blurSizeXY;
struct data {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 position : POSITION;
float4 screenPos : TEXCOORD0;
};
v2f vert(data i){
v2f o;
o.position = UnityObjectToClipPos(i.vertex);
o.screenPos = o.position;
return o;
}
half4 frag( v2f i ) : COLOR
{
float2 screenPos = i.screenPos.xy / i.screenPos.w;
float depth= _blurSizeXY*0.0005;
screenPos.x = (screenPos.x + 1) * 0.5;
screenPos.y = 1-(screenPos.y + 1) * 0.5;
half4 sum = half4(0.0h,0.0h,0.0h,0.0h);
sum += tex2D( _GrabTexture, float2(screenPos.x-5.0 * depth, screenPos.y+5.0 * depth)) * 0.025;
sum += tex2D( _GrabTexture, float2(screenPos.x+5.0 * depth, screenPos.y-5.0 * depth)) * 0.025;
sum += tex2D( _GrabTexture, float2(screenPos.x-4.0 * depth, screenPos.y+4.0 * depth)) * 0.05;
sum += tex2D( _GrabTexture, float2(screenPos.x+4.0 * depth, screenPos.y-4.0 * depth)) * 0.05;
sum += tex2D( _GrabTexture, float2(screenPos.x-3.0 * depth, screenPos.y+3.0 * depth)) * 0.09;
sum += tex2D( _GrabTexture, float2(screenPos.x+3.0 * depth, screenPos.y-3.0 * depth)) * 0.09;
sum += tex2D( _GrabTexture, float2(screenPos.x-2.0 * depth, screenPos.y+2.0 * depth)) * 0.12;
sum += tex2D( _GrabTexture, float2(screenPos.x+2.0 * depth, screenPos.y-2.0 * depth)) * 0.12;
sum += tex2D( _GrabTexture, float2(screenPos.x-1.0 * depth, screenPos.y+1.0 * depth)) * 0.15;
sum += tex2D( _GrabTexture, float2(screenPos.x+1.0 * depth, screenPos.y-1.0 * depth)) * 0.15;
sum += tex2D( _GrabTexture, screenPos-5.0 * depth) * 0.025;
sum += tex2D( _GrabTexture, screenPos-4.0 * depth) * 0.05;
sum += tex2D( _GrabTexture, screenPos-3.0 * depth) * 0.09;
sum += tex2D( _GrabTexture, screenPos-2.0 * depth) * 0.12;
sum += tex2D( _GrabTexture, screenPos-1.0 * depth) * 0.15;
sum += tex2D( _GrabTexture, screenPos) * 0.16;
sum += tex2D( _GrabTexture, screenPos+5.0 * depth) * 0.15;
sum += tex2D( _GrabTexture, screenPos+4.0 * depth) * 0.12;
sum += tex2D( _GrabTexture, screenPos+3.0 * depth) * 0.09;
sum += tex2D( _GrabTexture, screenPos+2.0 * depth) * 0.05;
sum += tex2D( _GrabTexture, screenPos+1.0 * depth) * 0.025;
return sum/2;
}
ENDCG
}
}
Fallback Off
}
How can I accomplish a glossy, or even just a highqaulity gaussian blur material for a mesh?
If you want to include a gloss onto your surface, here is one way to do it, based on the shader in the Glossy Textures article in the Unity Community wiki copied below:
Shader "Cg per-pixel lighting with texture" { Properties { _MainTex ("RGBA Texture For Material Color", 2D) = "white" {} _Color ("Diffuse Material Color", Color) = (1,1,1,1) _SpecColor ("Specular Material Color", Color) = (1,1,1,1) _Shininess ("Shininess", Float) = 10 } SubShader { Pass { Tags { "LightMode" = "ForwardBase" } // pass for ambient light and first light source CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform float4 _LightColor0; // color of light source (from "Lighting.cginc") // User-specified properties uniform sampler2D _MainTex; uniform float4 _Color; uniform float4 _SpecColor; uniform float _Shininess; struct vertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; }; struct vertexOutput { float4 pos : SV_POSITION; float4 posWorld : TEXCOORD0; float3 normalDir : TEXCOORD1; float4 tex : TEXCOORD2; }; vertexOutput vert(vertexInput input) { vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld; float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex); output.normalDir = normalize( mul(float4(input.normal, 0.0), modelMatrixInverse).xyz); output.tex = input.texcoord; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); return output; } float4 frag(vertexOutput input) : COLOR { float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize( _WorldSpaceCameraPos - input.posWorld.xyz); float3 lightDirection; float attenuation; float4 textureColor = tex2D(_MainTex, input.tex.xy); if (0.0 == _WorldSpaceLightPos0.w) // directional light? { attenuation = 1.0; // no attenuation lightDirection = normalize(_WorldSpaceLightPos0.xyz); } else // point or spot light { float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - input.posWorld.xyz; float distance = length(vertexToLightSource); attenuation = 1.0 / distance; // linear attenuation lightDirection = normalize(vertexToLightSource); } float3 ambientLighting = textureColor.rgb * UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection = textureColor.rgb * attenuation * _LightColor0.rgb * _Color.rgb * max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection; if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side? { specularReflection = float3(0.0, 0.0, 0.0); // no specular reflection } else // light source on the right side { specularReflection = attenuation * _LightColor0.rgb * _SpecColor.rgb * (1.0 - textureColor.a) // for usual gloss maps: "... * textureColor.a" * pow(max(0.0, dot( reflect(-lightDirection, normalDirection), viewDirection)), _Shininess); } return float4(ambientLighting + diffuseReflection + specularReflection, 1.0); } ENDCG } Pass { Tags { "LightMode" = "ForwardAdd" } // pass for additional light sources Blend One One // additive blending CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform float4 _LightColor0; // color of light source (from "Lighting.cginc") // User-specified properties uniform sampler2D _MainTex; uniform float4 _Color; uniform float4 _SpecColor; uniform float _Shininess; struct vertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; }; struct vertexOutput { float4 pos : SV_POSITION; float4 posWorld : TEXCOORD0; float3 normalDir : TEXCOORD1; float4 tex : TEXCOORD2; }; vertexOutput vert(vertexInput input) { vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld; float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex); output.normalDir = normalize( mul(float4(input.normal, 0.0), modelMatrixInverse).xyz); output.tex = input.texcoord; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); return output; } float4 frag(vertexOutput input) : COLOR { float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize( _WorldSpaceCameraPos - input.posWorld.xyz); float3 lightDirection; float attenuation; float4 textureColor = tex2D(_MainTex, input.tex.xy); if (0.0 == _WorldSpaceLightPos0.w) // directional light? { attenuation = 1.0; // no attenuation lightDirection = normalize(_WorldSpaceLightPos0.xyz); } else // point or spot light { float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - input.posWorld.xyz; float distance = length(vertexToLightSource); attenuation = 1.0 / distance; // linear attenuation lightDirection = normalize(vertexToLightSource); } float3 diffuseReflection = textureColor.rgb * attenuation * _LightColor0.rgb * _Color.rgb * max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection; if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side? { specularReflection = float3(0.0, 0.0, 0.0); // no specular reflection } else // light source on the right side { specularReflection = attenuation * _LightColor0.rgb * _SpecColor.rgb * (1.0 - textureColor.a) // for usual gloss maps: "... * textureColor.a" * pow(max(0.0, dot( reflect(-lightDirection, normalDirection), viewDirection)), _Shininess); } return float4(diffuseReflection + specularReflection, 1.0); // no ambient lighting in this pass } ENDCG } } Fallback "Specular" }
The final Pass
of your blur shader will need to be merged into the first and second Pass
es in the above shader.
Add these properties in the blur shader if they don't already exist (you may need to rename things if they do):
_MainTex ("RGBA Texture For Material Color", 2D) = "white" {}
_Color ("Diffuse Material Color", Color) = (1,1,1,1)
_SpecColor ("Specular Material Color", Color) = (1,1,1,1)
_Shininess ("Shininess", Float) = 10
Set the tag to match the glossy shader: "LightMode" = "ForwardBase"
Add these variables to the pass if they don't already exist (you may need to rename things if they do):
uniform sampler2D _MainTex;
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
Include float3 normal : NORMAL;
in your vertex input structure.
Include float4 posWorld : TEXCOORD0;
and float3 normalDir : TEXCOORD1;
in your vertex output structure.
In the vert
function, set output.posWorld
and output.normalDir
the same way the glossy shader vert
does.
Then, in the frag
function, take what your blur shader is already returning, and instead of returning it, use it as the textureColor
variable in the 1st frag
function in the glossy shader, and then do the rest of the 1st glossy frag
.
You will probably have to rename other things in the code to make it work with the pass you already have. I don't know what your blur shader looks like, so it's impossible for me to list every step in merging the two passes together.
Repeat the same process as the first gloss Pass
, but using the code from the 2nd gloss Pass
(especially important is the different tag "LightMode" = "ForwardAdd"
)