🌠
Siv3D | シェーダを使った表現集 (2D)
1. UV 座標をずらして画像から球を作る
# include <Siv3D.hpp> // OpenSiv3D v0.6.3
struct SphereParam
{
float offset;
};
void Main()
{
Window::Resize(1280, 720);
const PixelShader ps = HLSL{ U"sphere.hlsl" }
| GLSL{ U"sphere.glsl", { { U"PSConstants2D", 0 }, { U"SphereParam", 1 } } };
if (not ps)
{
throw Error{ U"Failed to load a shader file" };
}
ConstantBuffer<SphereParam> cb;
const Texture textureB{ U"example/texture/earth.jpg", TextureDesc::Mipped };
while (System::Update())
{
cb->offset = static_cast<float>(Scene::Time() * -0.1);
Graphics2D::SetPSConstantBuffer(1, cb);
{
const ScopedRenderStates2D sampler{ SamplerState::RepeatLinear };
const ScopedCustomShader2D shader{ ps };
Circle{ Scene::Center(), 220 }(textureB).draw();
}
}
}
sphere.hlsl
//
// Textures
//
Texture2D g_texture0 : register(t0);
SamplerState g_sampler0 : register(s0);
namespace s3d
{
//
// VS Output / PS Input
//
struct PSInput
{
float4 position : SV_POSITION;
float4 color : COLOR0;
float2 uv : TEXCOORD0;
};
}
//
// Constant Buffer
//
cbuffer PSConstants2D : register(b0)
{
float4 g_colorAdd;
float4 g_sdfParam;
float4 g_sdfOutlineColor;
float4 g_sdfShadowColor;
float4 g_internal;
}
cbuffer SphereParam : register(b1)
{
float g_offset;
}
//
// Functions
//
float4 PS(s3d::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.frag
# version 410
//
// Textures
//
uniform sampler2D Texture0;
//
// PSInput
//
layout(location = 0) in vec4 Color;
layout(location = 1) in vec2 UV;
//
// PSOutput
//
layout(location = 0) out vec4 FragColor;
//
// Constant Buffer
//
layout(std140) uniform PSConstants2D
{
vec4 g_colorAdd;
vec4 g_sdfParam;
vec4 g_sdfOutlineColor;
vec4 g_sdfShadowColor;
vec4 g_internal;
};
layout(std140) uniform SphereParam
{
float g_offset;
};
//
// Functions
//
void main()
{
vec2 centeredUV = (UV * 2.0f - 1.0f);
float z = sqrt(1.0f - clamp(dot(centeredUV.xy, centeredUV.xy), 0.0f, 1.0f));
vec2 sphereUV = centeredUV / (z + 1.0f);
vec2 uv = (sphereUV * 0.5f + 0.5f);
uv.x = uv.x / 2.0f + g_offset;
vec4 texColor = texture(Texture0, uv);
FragColor = ((texColor * Color) + g_colorAdd);
}
Discussion