みなさま、始めまして。
4月に入社した、新人プログラマーのふじひーです。
プログラムのネタを何かやろうかと思いましたが、にわかプログラマーの僕が適当な事かいてボコボコにされる未来が見えたので、全く需要の無い事にします。
需要の無い事それはずばり、ラーメン作りをして見ようと思います。
では早速、作り始めていきます。
ラーメンと言ったらまずは麺ですよね。
という事でパスタを用意します。

茹でないと食べられないので茹でます。

大体バリカタくらいでしょうか。
え?本物のラーメンじゃないって?
勿論料理スキルは0なので全く需要の無いシェーダーで作っていきます。
麺だけじゃまだラーメンには見えないですよね。と言うか食べ物にも見えない。
きっとラーメンどんぶりがないのでラーメンに見えないのでしょう。

ラーメンどんぶりも用意しました。
立体には見えないですが仕方が無いです。
モデリングツールもイラストツールを持っていないのでシェーダーで頑張ります。
さっき茹でたパスタを盛り付ける為に余分な部分を捨てて盛り付けましょう。

合体!

カップラーメンを上から覗いたように見えるような見えないような。
あとはスープが無いとただの素麺になってしまうのでスープを作ります。

作りすぎました。
素材は揃ったので全部盛り付けて

完成しました。
か、完成しました。
う~ん。
メシテロ感0ですね。
具も何も無いし、スペキュラーも無いので立体感もありません。
でも安心してください、好きな具材を乗せられるようにソースコードを公開します。
お好きにチャーシューでも乗せてください。
それでは。
以下ラーメンソースコード。
// ノイズの生成は
// https://github.com/ashima/webgl-noise
// ここからお借りしました。
float snoise(float3 v);
// アルファブレンド
float3 blend(float3 col1, float3 col2, float a)
{
return col1 * a + col2 * (1 - a);
}
// 麺を1玉作る
float4 tama(float2 uv, float menCount)
{
float menVol = 0.7;
float2 uvVec = uv * 2 - 1;
float uvLen = length(uvVec);
float vol = -uvLen + menVol;
vol = max(vol, 0);
// 茹でる前のパスタを並べる
float h = sin(fmod(uv.x * PI * menCount, PI * 2)) * vol;
float a = step(0.1, h);
h = max(h, 0);
h = lerp(0.5, 1, h);
return float4(h.xxx, a);
}
// 麺を茹でる
float2 boil(float2 uv, float3 seed)
{
// 麺が柔らかくなる
float d = snoise(seed);
uv.x += d * 0.01;
return uv;
}
// 麺を作る
float4 makeMen(float2 uv)
{
float4 col;
float4 yudeMen;
// 麺を1玉茹でる
col = tama(boil(uv, float3(uv * 20, 2)), 60);
// 麺を1玉茹でる
yudeMen = tama(boil(uv.yx, float3(uv * 10, 0.5)), 60);
col.rgb = blend(col.rgb, yudeMen.rgb, col.a);
col.a = min(yudeMen.a + col.a, 1);
// 麺を1玉茹でる
yudeMen = tama(boil(uv, float3(uv * 15, 1)), 40);
col.rgb = blend(col.rgb, yudeMen.rgb, col.a);
col.a = min(yudeMen.a + col.a, 1);
col = min(col, float4(1, 1, 1, 1));
return col;
}
// どんぶりを作る
float makeDonburi(float2 uv, out float inside, out float depth)
{
float donburiSize = 0.8;
float thickness = 0.05;
float2 uvVec = uv * 2 - 1;
float uvLen = length(uvVec);
// どんぶりの厚み
inside = step(uvLen, donburiSize - thickness);
float outside = step(uvLen, donburiSize);
// どんぶりの内側
float inner = uvLen / (1 - thickness);
depth = 1-inner;
inner = pow(inner, 5.0);
inner = lerp(0.2, 0.9, inner);
inner *= inside;
// どんぶり合体
return outside * (1 - inside) + inner;
}
// スープを作る
float4 makeSoup(float2 uv, float depth)
{
// 油っぽいのを浮かせる
float h = clamp(snoise(float3(uv * 8, 20)), 0, 1);
h = pow(h, 0.4);
float col = lerp(0.7, 1.0, h);
// スープを注ぐ
depth = smoothstep(0.25, 1, depth);
depth = pow(depth, 0.2);
return float4(col.xxx, depth);
}
// ラーメンを作る
float4 makeRamen(float2 uv)
{
float3 menColor = float3(1, 1, 0.38);
float3 soupColor = float3(0.93, 0.64, 0.1);
float3 col = float3(1.0, 1.0, 1.0);
// どんぶりを作る
float inside;
float depth;
float donburi = makeDonburi(uv, inside, depth);
// 麺を作る
float4 menCol;
menCol = makeMen(uv);
// (どんぶりに入らない部分は捨てる)
menCol *= inside;
// スープを作る
float4 soupCol = makeSoup(uv, depth);
soupCol *= inside;
// 盛り付け
col = donburi.xxx;
col = blend(menCol.rgb * menColor, col, menCol.a);
col = blend(soupCol.rgb * soupColor, col, soupCol.a);
return float4(col, 1);
}

