OpenSiv3D | シェーダを使った表現集 (2D)

3 min read読了の目安(約1800字

1. UV 座標をずらして画像から球を作る

準備:
地球の 2:1 の画像を https://www.nasa.gov/vision/earth/lookingatearth/earthweek.html からダウンロードして、App フォルダに earth.jpg として保存。

# include <Siv3D.hpp> // OpenSiv3D v0.4.3

struct SphereParam
{
	float offset;
	Float3 _unused;
};

void Main()
{
	Window::Resize(1280, 720);

	const PixelShader ps(U"sphere.hlsl", { { U"PSConstants2D", 0 }, { U"SphereParam", 1 } });
	if (!ps)
	{
		throw Error(U"Failed to load a shader file");
	}

	ConstantBuffer<SphereParam> cb;

	// 横縦が 2 : 1 の比率のテクスチャを使う
	const Texture textureB(U"earth.jpg", TextureDesc::Mipped);

	while (System::Update())
	{
		cb->offset = static_cast<float>(Scene::Time() * -0.1);
		Graphics2D::SetConstantBuffer(ShaderStage::Pixel, 1, cb);

		{
			ScopedRenderStates2D sampler(SamplerState::RepeatLinear);
			ScopedCustomShader2D shader(ps);
			Circle(Scene::Center(), 220)(textureB).draw();
		}
	}
}

sphere.hlsl

Texture2D g_texture0 : register(t0);
SamplerState g_sampler0 : register(s0);

cbuffer PSConstants2D : register(b0)
{
	float4 g_colorAdd;
	float4 g_sdfParam;
	float4 g_internal;
}

cbuffer SphereParam : register(b1)
{
	float g_offset;
}

struct PSInput
{
	float4 position : SV_POSITION;
	float4 color : COLOR0;
	float2 uv : TEXCOORD0;
};

float4 PS(PSInput input) : SV_TARGET
{
	float2 centeredUV = (input.uv * 2.0 - 1.0);
	float z = sqrt(1.0 - saturate(dot(centeredUV.xy, centeredUV.xy)));
	float2 sphereUV = centeredUV / (z + 1.0);
	float2 uv = (sphereUV * 0.5 + 0.5);
	uv.x = uv.x / 2 + g_offset;
	float4 texColor = g_texture0.Sample(g_sampler0, uv);
	return (texColor * input.color) + g_colorAdd;
}

sphere.glsl

(準備中)

参考資料