I am trying to make a smooth mesh look flat, flattening the normals of each polygons with this shader but getting errors, can someone help out with GLSL (would use sorface shading but I don’t think the flat attribute exists)
Shader "Flattener" {
SubShader {
Pass {
GLSLPROGRAM
#extension GL_EXT_gpu_shader4 : require
flat varying vec4 color;
#ifdef VERTEX
void main()
{
color = gl_Color;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#endif
#ifdef FRAGMENT
void main()
{
gl_FragColor = color; // set the output fragment color
}
#endif
ENDGLSL
}
}
}
That extension being not supported seems very clear to me, don’t know what you need help with. (did you try to remove that extension line? not sure what needs it, then again I really don’t know much about glsl).
I’m pretty sure vec4 is not valid in Unity. Change it to half4 or float4. As for the other error, it looks like GL_EXT_gpu_shader4 simply isn’t supported, either by Unity or your computer.
Also, can you describe what you mean by “flat shaded”? Try selecting your model, and in the import settings change “Normals” from “Import” to “Calculate”, then mode the slider to 0. Is this what you want?
I believe flat was added in OpenGL 3.0, maybe 3.1, but Unity might be trying to compile to 2.0.
You might try adding: #version 130
Or #version 140
To force OpenGL 3.0 or 3.1 respectively. I assume those work in Unity with GLSLPROGRAM blocks, I don’t know for sure as I rarely do direct GLSL or HLSL programming with in Unity.
Alternately you could try writing it as a normal Unity shader within a CGPROGRAM and use the nointerpolation qualifier along with #pragma target 4.0
THANKS bgolus ! Just adding nointerpolation in front of the color v2f does the magic!
Most of my shaders are surface shader, nointerpolation gives a syntax error, do you know what the surface shader equivalent is?
magic flat shader
Shader "Diffuse With Shadows"
{
Properties
{
[NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
Tags {"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
// compile shader into multiple variants, with and without shadows
// (we don't care about any lightmaps yet, so skip these variants)
#pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
// shadow helper functions and macros
#include "AutoLight.cginc"
struct v2f
{
float2 uv : TEXCOORD0;
SHADOW_COORDS(1) // put shadows data into TEXCOORD1
nointerpolation fixed3 diff : COLOR0;
nointerpolation fixed3 ambient : COLOR1;
float4 pos : SV_POSITION;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord;
half3 worldNormal = UnityObjectToWorldNormal(v.normal);
half nl = max(0, dot(worldNormal, _WorldSpaceLightPos0.xyz));
o.diff = nl * _LightColor0.rgb;
o.ambient = ShadeSH9(half4(worldNormal,1));
// compute shadows data
TRANSFER_SHADOW(o)
return o;
}
sampler2D _MainTex;
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
// compute shadow attenuation (1.0 = fully lit, 0.0 = fully shadowed)
fixed shadow = SHADOW_ATTENUATION(i);
// darken light's illumination with shadow, keep ambient intact
fixed3 lighting = i.diff * shadow + i.ambient;
col.rgb *= lighting;
return col;
}
ENDCG
}
// shadow casting support
UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
}
}
Hello, can anyone explain what happens when you use the keyword “nointerpolation”, the entire triangle is filled with the value calculated for the first vertex?
Unlit shaders are, well, unlit, sometimes erroneously referred to as “flat shading” or “flatly lit”, but unlit shaders aren’t lit or really “shaded” at all. The flat shading being discussed here, and specifically the GLSL “flat” and HLSL “nointerpolation”, allows for faceted surface shading without having faceted model normals. What the OP is referring to is the “PolyWorld” style faceted surface shading, like this:
The example shader at the start is just testing the GLSL “flat” attribute designation rather than an attempt at the final flat shaded result.
Does that mean it is possible to keep a low vertices count while having the flat style? A visually faceted cube (custom one not the Unity one) will still have 8 vertices instead of 24?
I guess my real question behind it is more how good is it performance wise?
Yep, you can have every vertex welded, though there’s a chance two polygons will end up with the same values if they share the same first vertex.
Performance wise there should be zero performance difference vs the same smooth mesh with a normal shader, and plausibly though unlikely even a very (very, very) minor perf gain over traditional interpolated attributes. On very high poly objects it might even be noticeably faster than manually faceted surfaces.
Unfortunately for the platforms that this would actually matter at these low poly counts, they don’t support nointerpolation / flat (low end mobile) so it’s kind of moot.