Hi all,
I’m looking to recreate this 3D wall effect in some capacity (from Portal in-game editor):
From this Pro-builder mesh (shader should keep modifying levels a non-destructive process hopefully):

I’m pretty new to shader programming so any advice/help would be very appreciated. I’ve slightly modified this shader from a YouTube tutorial and got the following result (code at bottom of post):

There’s a few issues:
- (A) Corners don’t connect
- (B) Generated mesh is messy
- (C) Walls nearest the camera don’t cull

From my limited shader knowledge, this is my current guess of what needs to be done:
(A) Move generated vertex along its normal (mesh will have to be smoothed)
(B) Skip vertexes that fail a condition (not quite sure what the condition would be yet)
(C) Do a cull pass first (?)
Any advice or help would be very valuable even if it’s just confirming I’m headed on the correct path. Thanks!
Shader "Custom/Geometry/Extrude"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Factor ("Factor", Range(-2., 2.)) = 0.2
_FrontColor("Front Color", Color) = (1.,1.,1.,1)
_BackColor("Back Color", Color) = (.0,.0,.0,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom
#include "UnityCG.cginc"
struct v2g
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct g2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
fixed4 col : COLOR;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2g vert (appdata_base v)
{
v2g o;
o.vertex = v.vertex;
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.normal = v.normal;
return o;
}
float _Factor;
fixed4 _FrontColor;
fixed4 _BackColor;
[maxvertexcount(24)]
void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)
{
g2f o;
float3 edgeA = IN[1].vertex - IN[0].vertex;
float3 edgeB = IN[2].vertex - IN[0].vertex;
float3 normalFace = normalize(cross(edgeA, edgeB));
for(int i = 0; i < 3; i++)
{
o.pos = UnityObjectToClipPos(IN[i].vertex);
o.uv = IN[i].uv;
o.col = _BackColor;
tristream.Append(o);
o.pos = UnityObjectToClipPos(IN[i].vertex + IN[i].normal * _Factor); //+ float4(normalFace, 0)
o.uv = IN[i].uv;
o.col = _FrontColor;
tristream.Append(o);
int inext = (i+1) % 3;
o.pos = UnityObjectToClipPos(IN[inext].vertex);
o.uv = IN[inext].uv;
o.col = _BackColor;
tristream.Append(o);
tristream.RestartStrip();
o.pos = UnityObjectToClipPos(IN[i].vertex + float4(normalFace, 0) * _Factor);
o.uv = IN[i].uv;
o.col = _FrontColor;
tristream.Append(o);
o.pos = UnityObjectToClipPos(IN[inext].vertex);
o.uv = IN[inext].uv;
o.col = _BackColor;
tristream.Append(o);
o.pos = UnityObjectToClipPos(IN[inext].vertex + float4(normalFace, 0) * _Factor);
o.uv = IN[inext].uv;
o.col = _FrontColor;
tristream.Append(o);
tristream.RestartStrip();
}
for(int i = 0; i < 3; i++)
{
o.pos = UnityObjectToClipPos(IN[i].vertex + float4(normalFace, 0) * _Factor);
o.uv = IN[i].uv;
o.col = _FrontColor;
tristream.Append(o);
}
tristream.RestartStrip();
for(int i = 0; i < 3; i++)
{
o.pos = UnityObjectToClipPos(IN[i].vertex);
o.uv = IN[i].uv;
o.col = _BackColor;
tristream.Append(o);
}
tristream.RestartStrip();
}
fixed4 frag (g2f i) : SV_Target
{
fixed4 col = ((tex2D(_MainTex, i.uv) * i.col) * i.col.a) + ((1-i.col.a) * _FrontColor);
return col;
}
ENDCG
}
}
}




