- Home /
Question by
PanzerPotato · Jun 28, 2018 at 04:50 PM ·
shadershadersshader programmingcgshader writing
Triplanar shaders that use the position and rotation of the attached object (or local Triplanar shaders)
Hi guys,
I've been using Unity for a while now, but I haven't even touched shaders. In the game I'm currently on, I want to create a shader for a camouflage that disregards the scale (and normals, I think?) of the object and only uses it's rotation and position. Here's what it should look like: The camouflage above uses a tri-planer shader, but the problem is that it's relative to the world rather to the object itself. Here's the code:
Shader "Custom/RelativeShader" {
Properties {
_Side("Side", 2D) = "white" {}
_Top("Top", 2D) = "white" {}
_Bottom("Bottom", 2D) = "white" {}
_SideScale("Side Scale", Float) = 2
_TopScale("Top Scale", Float) = 2
_BottomScale ("Bottom Scale", Float) = 2
}
SubShader {
Tags {
"Queue"="Geometry"
"IgnoreProjector"="False"
"RenderType"="Opaque"
}
Cull Back
ZWrite On
CGPROGRAM
#pragma surface surf Lambert
#pragma exclude_renderers flash
sampler2D _Side, _Top, _Bottom;
float _SideScale, _TopScale, _BottomScale;
struct Input {
float3 worldPos;
float3 worldNormal;
};
void surf (Input IN, inout SurfaceOutput o) {
float3 projNormal = saturate(pow(IN.worldNormal * 1.4, 4));
// SIDE X
float3 x = tex2D(_Side, frac(IN.worldPos.zy * _SideScale)) * abs(IN.worldNormal.x);
// TOP / BOTTOM
float3 y = 0;
if (IN.worldNormal.y > 0) {
y = tex2D(_Top, frac(IN.worldPos.zx * _TopScale)) * abs(IN.worldNormal.y);
} else {
y = tex2D(_Bottom, frac(IN.worldPos.zx * _BottomScale)) * abs(IN.worldNormal.y);
}
// SIDE Z
float3 z = tex2D(_Side, frac(IN.worldPos.xy * _SideScale)) * abs(IN.worldNormal.z);
o.Albedo = z;
o.Albedo = lerp(o.Albedo, x, projNormal.x);
o.Albedo = lerp(o.Albedo, y, projNormal.y);
}
ENDCG
}
Fallback "Diffuse"
}
Any ideas or alternatives are appreciated, and thanks in advance for your time!
screenshot.png
(89.4 kB)
Comment