47
38

More than 3 years have passed since last update.

ジオメトリシェーダー基本図形コード集

Last updated at Posted at 2019-10-16

ShaderLabのジオメトリシェーダで以下のような形状を生成するベタ書きコード集です。

GeomPrim.gif

正四面体

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
}
}
}
47
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
38