ShaderLabのジオメトリシェーダで以下のような形状を生成するベタ書きコード集です。
正四面体
Shader "Yagiri/GeometryShader/Primitive/Tetrahedron"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
#include "UnityCG.cginc"
#define PI2 6.28318530718
struct appdata
{
float4 vertex : POSITION;
};
struct v2g
{
float4 pos : POSITION;
};
struct g2f
{
float4 pos : SV_POSITION;
float3 normal : NORMAL;
};
v2g vert(appdata v)
{
v2g o;
o.pos = v.vertex;
return o;
}
static const float3 vertexs[12] =
{
float3(0.0, 0.5, 0.0),
float3(0.235703, -0.166665, 0.408249),
float3(0.235703, -0.166665, -0.408249),
float3(0.0, 0.5, 0.0),
float3(0.235703, -0.166665, -0.408249),
float3(-0.471405, -0.166665, 0.0),
float3(0.0, 0.5, 0.0),
float3(-0.471405, -0.166665, 0.0),
float3(0.235703, -0.166665, 0.408249),
float3(-0.471405, -0.166665, 0.0),
float3(0.235703, -0.166665, -0.408249),
float3(0.235703, -0.166665, 0.408249)
};
static const float3 normals[4] =
{
float3(0.942809,0.333335,-0.0),
float3(-0.471404,0.333335,-0.816496),
float3(-0.471404,0.333335,0.816496),
float3(0.0,-1.0,0.0)
};
[maxvertexcount(12)]
void geom(point v2g input[1], uint id : SV_PrimitiveID, inout TriangleStream<g2f> outStream)
{
g2f o;
[unroll]
for(int j = 0; j < 4; j++)
{
[unroll]
for (int k = 0; k < 3; k++)
{
const int vid = j * 3 + k;
o.pos = float4(vertexs[vid], 1.0);
o.pos = UnityObjectToClipPos(o.pos);
o.normal = UnityObjectToWorldNormal(normals[j]);
outStream.Append(o);
}
outStream.RestartStrip();
}
}
fixed4 frag(g2f i) : SV_Target
{
float4 col = 1;
float3 lightdir = _WorldSpaceLightPos0.xyz;
col.xyz *= saturate(dot(i.normal, -lightdir));
return col;
}
ENDCG
}
}
}
立方体
Shader "Yagiri/GeometryShader/Primitive/Cube"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
#include "UnityCG.cginc"
#define PI2 6.28318530718
// vertex shaderに入る構造体
struct appdata
{
float4 vertex : POSITION;
};
// vertex shader から geometry shaderに渡る構造体
struct v2g{
float4 pos : POSITION;
};
// geometry shaderからfragment shaderに渡る構造体
struct g2f
{
float4 pos : SV_POSITION;
float3 normal : NORMAL;
};
v2g vert(appdata v)
{
v2g o;
o.pos = v.vertex;
return o;
}
static const float3 vertexs[24] = {
float3(0.5, -0.5, 0.5),
float3(0.5, 0.5, 0.5),
float3(-0.5, -0.5, 0.5),
float3(-0.5, 0.5, 0.5),
float3(-0.5, -0.5, -0.5),
float3(-0.5, 0.5, -0.5),
float3(0.5, -0.5, -0.5),
float3(0.5, 0.5, -0.5),
float3(-0.5, 0.5, -0.5),
float3(-0.5, 0.5, 0.5),
float3(0.5, 0.5, -0.5),
float3(0.5, 0.5, 0.5),
float3(0.5, -0.5, -0.5),
float3(0.5, -0.5, 0.5),
float3(-0.5, -0.5, -0.5),
float3(-0.5, -0.5, 0.5),
float3(0.5, -0.5, -0.5),
float3(0.5, 0.5, -0.5),
float3(0.5, -0.5, 0.5),
float3(0.5, 0.5, 0.5),
float3(-0.5, -0.5, 0.5),
float3(-0.5, 0.5, 0.5),
float3(-0.5, -0.5, -0.5),
float3(-0.5, 0.5, -0.5)
};
static const float3 normals[6] =
{
float3(0.0,0.0,1.0),
float3(0.0,0.0,-1.0),
float3(0.0,1.0,0.0),
float3(0.0,-1.0,0.0),
float3(1.0,0.0,0.0),
float3(-1.0,0.0,0.0)
};
[maxvertexcount(24)]
void geom(point v2g input[1], uint id : SV_PrimitiveID, inout TriangleStream<g2f> outStream)
{
g2f o;
[unroll]
for(int j = 0; j < 6; j++)
{
[unroll]
for (int k = 0; k < 4; k++)
{
const int vid = j * 4 + k;
o.pos = float4(vertexs[vid], 1.0);
o.pos = UnityObjectToClipPos(o.pos);
o.normal = UnityObjectToWorldNormal(normals[j]);
outStream.Append(o);
}
outStream.RestartStrip();
}
}
fixed4 frag(g2f i) : SV_Target
{
float4 col = 1;
float3 lightdir = _WorldSpaceLightPos0.xyz;
col.xyz *= saturate(dot(i.normal, -lightdir));
return col;
}
ENDCG
}
}
}
正八面体
Shader "Yagiri/GeometryShader/Primitive/Octahedron"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
#include "UnityCG.cginc"
#define PI2 6.28318530718
// vertex shaderに入る構造体
struct appdata
{
float4 vertex : POSITION;
};
// vertex shader から geometry shaderに渡る構造体
struct v2g{
float4 pos : POSITION;
};
// geometry shaderからfragment shaderに渡る構造体
struct g2f
{
float4 pos : SV_POSITION;
float3 normal : NORMAL;
};
v2g vert(appdata v)
{
v2g o;
o.pos = v.vertex;
return o;
}
static const float3 vertexs[24] =
{
float3(0.0, 0.0, -0.5),
float3(0.0, -0.5, 0.0),
float3(-0.5, 0.0, 0.0),
float3(0.0, 0.0, -0.5),
float3(0.5, 0.0, 0.0),
float3(0.0, -0.5, 0.0),
float3(0.5, 0.0, 0.0),
float3(0.0, 0.0, 0.5),
float3(0.0, -0.5, 0.0),
float3(0.0, 0.0, 0.5),
float3(-0.5, 0.0, 0.0),
float3(0.0, -0.5, 0.0),
float3(0.0, 0.0, -0.5),
float3(-0.5, 0.0, 0.0),
float3(0.0, 0.5, 0.0),
float3(0.0, 0.0, -0.5),
float3(0.0, 0.5, 0.0),
float3(0.5, 0.0, 0.0),
float3(0.5, 0.0, 0.0),
float3(0.0, 0.5, 0.0),
float3(0.0, 0.0, 0.5),
float3(0.0, 0.0, 0.5),
float3(0.0, 0.5, 0.0),
float3(-0.5, 0.0, 0.0)
};
static const float3 normals[8] =
{
float3(-0.57735,-0.57735,-0.57735),
float3(0.57735,-0.57735,-0.57735),
float3(0.57735,-0.57735,0.57735),
float3(-0.57735,-0.57735,0.57735),
float3(-0.57735,0.57735,-0.57735),
float3(0.57735,0.57735,-0.57735),
float3(0.57735,0.57735,0.57735),
float3(-0.57735,0.57735,0.57735),
};
[maxvertexcount(24)]
void geom(point v2g input[1], uint id : SV_PrimitiveID, inout TriangleStream<g2f> outStream)
{
g2f o;
[unroll]
for(int j = 0; j < 8; j++)
{
[unroll]
for (int k = 0; k < 3; k++)
{
const int vid = j * 3 + k;
o.pos = float4(vertexs[vid], 1.0);
o.pos = UnityObjectToClipPos(o.pos);
o.normal = UnityObjectToWorldNormal(normals[j]);
outStream.Append(o);
}
outStream.RestartStrip();
}
}
fixed4 frag(g2f i) : SV_Target
{
float4 col = 1;
float3 lightdir = _WorldSpaceLightPos0.xyz;
col.xyz *= saturate(dot(i.normal, -lightdir));
return col;
}
ENDCG
}
}
}
正二十面体
Shader "Yagiri/GeometryShader/Primitive/Icosahedron"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
#include "UnityCG.cginc"
#define PI2 6.28318530718
// vertex shaderに入る構造体
struct appdata
{
float4 vertex : POSITION;
};
// vertex shader から geometry shaderに渡る構造体
struct v2g{
float4 pos : POSITION;
};
// geometry shaderからfragment shaderに渡る構造体
struct g2f
{
float4 pos : SV_POSITION;
float3 normal : NORMAL;
};
v2g vert(appdata v)
{
v2g o;
o.pos = v.vertex;
return o;
}
static const float3 vertexs[60] =
{
float3(0.425325, 0.138197, -0.223607),
float3(0.0, 0.0, -0.5),
float3(0.0, 0.447214, -0.223607),
float3(0.262866, -0.361803, -0.223607),
float3(0.0, 0.0, -0.5),
float3(0.425325, 0.138197, -0.223607),
float3(-0.262866, -0.361803, -0.223607),
float3(0.0, 0.0, -0.5),
float3(0.262866, -0.361803, -0.223607),
float3(-0.425325, 0.138197, -0.223607),
float3(0.0, 0.0, -0.5),
float3(-0.262866, -0.361803, -0.223607),
float3(0.0, 0.447214, -0.223607),
float3(0.0, 0.0, -0.5),
float3(-0.425325, 0.138197, -0.223607),
float3(-0.262866, 0.361803, 0.223607),
float3(0.0, 0.447214, -0.223607),
float3(-0.425325, 0.138197, -0.223607),
float3(-0.425325, -0.138197, 0.223607),
float3(-0.425325, 0.138197, -0.223607),
float3(-0.262866, -0.361803, -0.223607),
float3(0.0, -0.447214, 0.223607),
float3(-0.262866, -0.361803, -0.223607),
float3(0.262866, -0.361803, -0.223607),
float3(0.425325, -0.138197, 0.223607),
float3(0.262866, -0.361803, -0.223607),
float3(0.425325, 0.138197, -0.223607),
float3(0.262866, 0.361803, 0.223607),
float3(0.425325, 0.138197, -0.223607),
float3(0.0, 0.447214, -0.223607),
float3(0.262866, 0.361803, 0.223607),
float3(0.0, 0.447214, -0.223607),
float3(-0.262866, 0.361803, 0.223607),
float3(-0.262866, 0.361803, 0.223607),
float3(-0.425325, 0.138197, -0.223607),
float3(-0.425325, -0.138197, 0.223607),
float3(-0.425325, -0.138197, 0.223607),
float3(-0.262866, -0.361803, -0.223607),
float3(0.0, -0.447214, 0.223607),
float3(0.0, -0.447214, 0.223607),
float3(0.262866, -0.361803, -0.223607),
float3(0.425325, -0.138197, 0.223607),
float3(0.425325, -0.138197, 0.223607),
float3(0.425325, 0.138197, -0.223607),
float3(0.262866, 0.361803, 0.223607),
float3(-0.262866, 0.361803, 0.223607),
float3(0.0, 0.0, 0.5),
float3(0.262866, 0.361803, 0.223607),
float3(0.262866, 0.361803, 0.223607),
float3(0.0, 0.0, 0.5),
float3(0.425325, -0.138197, 0.223607),
float3(0.425325, -0.138197, 0.223607),
float3(0.0, 0.0, 0.5),
float3(0.0, -0.447214, 0.223607),
float3(0.0, -0.447214, 0.223607),
float3(0.0, 0.0, 0.5),
float3(-0.425325, -0.138197, 0.223607),
float3(-0.425325, -0.138197, 0.223607),
float3(0.0, 0.0, 0.5),
float3(-0.262866, 0.361803, 0.223607)
};
static const float3 normals[20] =
{
float3(0.356822,0.491124,-0.794654),
float3(0.577351,-0.187592,-0.794654),
float3(0.0,-0.607062,-0.794654),
float3(-0.577351,-0.187592,-0.794654),
float3(-0.356822,0.491124,-0.794654),
float3(-0.57735,0.794655,-0.187593),
float3(-0.934172,-0.303531,-0.187593),
float3(-0.0,-0.982247,-0.187593),
float3(0.934172,-0.303531,-0.187593),
float3(0.57735,0.794655,-0.187593),
float3(0.0,0.982247,0.187593),
float3(-0.934172,0.303531,0.187593),
float3(-0.57735,-0.794655,0.187593),
float3(0.57735,-0.794655,0.187593),
float3(0.934172,0.303531,0.187593),
float3(-0.0,0.607062,0.794654),
float3(0.577351,0.187592,0.794654),
float3(0.356822,-0.491124,0.794654),
float3(-0.356822,-0.491124,0.794654),
float3(-0.577351,0.187592,0.794654),
};
[maxvertexcount(60)]
void geom(point v2g input[1], uint id : SV_PrimitiveID, inout TriangleStream<g2f> outStream)
{
g2f o;
[unroll]
for(int j = 0; j < 20; j++)
{
[unroll]
for (int k = 0; k < 3; k++)
{
const int vid = j * 3 + k;
o.pos = float4(vertexs[vid], 1.0);
o.pos = UnityObjectToClipPos(o.pos);
o.normal = UnityObjectToWorldNormal(normals[j]);
outStream.Append(o);
}
outStream.RestartStrip();
}
}
fixed4 frag(g2f i) : SV_Target
{
float4 col = 1;
float3 lightdir = _WorldSpaceLightPos0.xyz;
col.xyz *= saturate(dot(i.normal, -lightdir));
return col;
}
ENDCG
}
}
}
リング, チューブ
Shader "Yagiri/GeometryShader/Primitive/RingAndTube"
{
Properties
{
_RadiusA("RadiusA", Float) = 0.5
_RadiusB("RadiusB", Float) = 0.3
_HeightA("HeightA", Float) = 0.0
_HeightB("HeightB", Float) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
#include "UnityCG.cginc"
#define PI2 6.28318530718
struct appdata
{
float4 vertex : POSITION;
};
struct v2g
{
float4 pos : POSITION;
};
struct g2f
{
float4 pos : SV_POSITION;
float3 normal : NORMAL;
};
v2g vert(appdata v)
{
v2g o;
o.pos = v.vertex;
return o;
}
float _RadiusA;
float _RadiusB;
float _HeightA;
float _HeightB;
// ※最大頂点数制限に注意
// RowN * Column * 4 = 96
[maxvertexcount(96)]
void geom(point v2g input[1], uint id : SV_PrimitiveID, inout TriangleStream<g2f> outStream)
{
g2f o;
const int RowN = 3;
const int ColumnN = 8;
[unroll]
for (int j = 0; j < ColumnN; j++)
{
float nj = j / (float)ColumnN;
float nj_ = (j + 1) / (float)ColumnN;
float3 top = float3(
_RadiusA * cos(PI2*nj),
_HeightA,
_RadiusA * sin(PI2*nj)
);
float3 bottom = float3(
_RadiusB * cos(PI2*nj),
_HeightB,
_RadiusB * sin(PI2*nj)
);
float3 top_ = float3(
_RadiusA * cos(PI2*nj_),
_HeightA,
_RadiusA * sin(PI2*nj_)
);
float3 bottom_ = float3(
_RadiusB * cos(PI2*nj_),
_HeightB,
_RadiusB * sin(PI2*nj_)
);
[unroll]
for(int k = 0; k < RowN; k++)
{
float nk = k / (float)RowN;
float nk_ = (k + 1) / (float)RowN;
float3 p0 = lerp(top, bottom, nk);
float3 p1 = lerp(top, bottom, nk_);
float3 p2 = lerp(top_, bottom_, nk);
float3 p3 = lerp(top_, bottom_, nk_);
float3 n = normalize(cross(p1 - p0, p2 - p0));
o.normal = UnityObjectToWorldNormal(n);
o.pos = UnityObjectToClipPos(float4(p0, 1.0));
outStream.Append(o);
o.pos = UnityObjectToClipPos(float4(p1, 1.0));
outStream.Append(o);
o.pos = UnityObjectToClipPos(float4(p2, 1.0));
outStream.Append(o);
o.pos = UnityObjectToClipPos(float4(p3, 1.0));
outStream.Append(o);
outStream.RestartStrip();
}
}
}
fixed4 frag(g2f i) : SV_Target
{
float4 col = 1;
float3 lightdir = _WorldSpaceLightPos0.xyz;
col.xyz *= saturate(dot(i.normal, -lightdir));
return col;
}
ENDCG
}
}
}