1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

映写機の演出っていいよね。よし作ろう。

1
Posted at

初投稿の記事になります。
至らぬところ多々あると思いますが、優しい目で見ていただけると嬉しいです

映写機ってなんかおしゃれだよねー

皆さんも思いませんか?映写機ってなんかエモいというか演出として良いものだと私は思います。
え?「映写機ってなんぞや?」
あらまぁ、ご存じない?
多分名称を知らないだけでは?おそらく皆さん見たことあるでしょう。
映写機といえばこんな感じ、これを参考に作っていきます
見たことあるでしょう?リンク先の映像にはないですけど、「カタカタ」という音を立てながら、色あせた背景にフィルムのような黒の帯が左右にある。(今回はゲーム内でユーザーの気を散らす目的で制作するので物理的な妨害となる左右帯は作りません)
さぁ、映写機の演出についてのイメージを立ててもらったところでシェーダー使って作っていきましょう!!

作るぞ~!

テキトーな背景を持ってきました。
スクリーンショット 2025-12-15 223301.png

1. まずは画面をあの色あせたセピア色にしていきましょう。
const float3 sepiaR = { 0.393f, 0.769f, 0.189f };
const float3 sepiaG = { 0.349f, 0.686f, 0.168f };
const float3 sepiaB = { 0.272f, 0.534f, 0.131f };

//本来出力されるカラー
 float4 col = tex.Sample(texSampler, PSInput.uv);

 //セピア色に調整
 float3 sepiaCol;
 sepiaCol.r = min(1.0f, col.r * sepiaR.r + col.g * sepiaR.g + col.b * sepiaR.b);
 sepiaCol.g = min(1.0f, col.r * sepiaG.r + col.g * sepiaG.g + col.b * sepiaG.b);
 sepiaCol.b = min(1.0f, col.r * sepiaB.r + col.g * sepiaB.g + col.b * sepiaB.b);

こんな感じになりました。
スクリーンショット 2025-12-15 222719.png

セピアになるといい気に古めかしさが増しますね。
参考元を見てみると、全体がセピア一色ではなく画面端付近が少し暗くなっています。

2. とりあえず画面端が暗く、画面中央が明るくなるようにしてみます。
 // UV中心からの距離
 float2 center = float2(0.5f, 0.5f);
 float2 diff = PSInput.uv - center;
 float dist = length(diff); // 0.0(中心)~ 約0.707(隅)

 // フェード効果(中心に近いほど減衰)
float edge = smoothstep(0.1, 0.8, dist);

// 最終色:時間に応じて赤がフェードイン・アウト
float4 black = float4(1.0, 1.0, 1.0, 1.0) * edge;

float3 useCol = sepiaCol - black.rgb;
return float4(useCol, 1.0f);

こんな感じになりました。
スクリーンショット 2025-12-15 225535.png

暗すぎますね。これでは左右帯と同義になるどころか上下まで増えてより凶悪になってしまいました。。
カラーを黒(1.0,1.0,1.0)ではなく灰色(0.5,0.5,0.5)に調節しときましょう。

3. 次にランダムの黒の縦線のノイズを入れてみます。

これが入るとフィルムの経年劣化の感じがでていいですよね。

//c++側
    //blackUVのX値
    float randomNoiseLineX = static_cast<float>(rand() % 100) / 100.0f;

//Shader側
cbuffer cbParam : register(b4)
{
    float2 blackUV;
}

//~(中略)~
    float3 useCol = sepiaCol - black.rgb;

   float diffNoiseLine = abs(PSInput.uv.x - blackUV.x);
   
   if (diffNoiseLine < 0.002f)
   {
       useCol = (0.0f, 0.0f, 0.0f);
   }

rand()関数を使用して、0.0~1.0までに収めたい!
しかし0.1単位でとってしまうと画面の一割を持っていかれるので、0.01単位に換算するようにしました。blacLine-ezgif.com-video-to-gif-converter.gif
いい感じですね。
あともう1つそれぽっさを加えるものを作っていきます。

4. それは「セピアの明るさのばらつき」です。

これもまた経年劣化を表すのに最適なものです。
映画のフィルムは月日が経つにつれ、日焼けして正常な明度ではなくなっていきます。
難しく考えたくないので、C++側から白の強さを受け取り色に加味していきましょう。

//c++側
    //blackUVのX値
    float randomNoiseLineX = static_cast<float>(rand() % 100) / 100.0f;
    //白の強さ
    float whitePoe = static_cast<float>(rand() % 100) / 1000.0f;

//Shader側
cbuffer cbParam : register(b4)
{
    float2 blackUV;
    float whitePow;
}

//~(中略)~
    //白の強さ加算
    sepiaCol += (whitePow, whitePow, whitePow);

//~(以下略)~

画面が白を強くなりすぎるのを防ぐため、static_cast<float>(rand() % 100) / 1000.0f; と分母を1000.0fにすることで、値を0.0~0.1に収めています。
blac_flash-ezgif.com-video-to-gif-converter.gif

いいですねぇ(愉悦)

まとめ

今回はこれで完成とします。
もっと凝れる部分はありますが、満足できるラインになったので良しとします。
決して他の作業が溜まっていて忙しくなったとかそんなんじゃn...
これからも、自分が好きな映像演出をシェーダで作成していこうと思います。
終わり。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?