Skip to content

Instantly share code, notes, and snippets.

@comefrombottom
Created February 22, 2024 17:50
Show Gist options
  • Save comefrombottom/e8e4d2b9e8cbb87cc54489cc9cb9e551 to your computer and use it in GitHub Desktop.
Save comefrombottom/e8e4d2b9e8cbb87cc54489cc9cb9e551 to your computer and use it in GitHub Desktop.
水面の揺らぎをシェーダで作ってみた。
//
// Textures
//
Texture2D g_texture0 : register(t0);
Texture2D g_texture1 : register(t1);
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 PixelSize : register(b1)
{
float2 g_pixelSize;
}
float4 PS(s3d::PSInput input) : SV_TARGET
{
float c = g_texture0.Sample(g_sampler0, input.uv).r;
float2 tan =
float2(
g_texture1.Sample(g_sampler0, input.uv + float2(g_pixelSize.x, 0)).r - g_texture1.Sample(g_sampler0, input.uv - float2(g_pixelSize.x, 0)).r,
g_texture1.Sample(g_sampler0, input.uv + float2(0, g_pixelSize.y)).r - g_texture1.Sample(g_sampler0, input.uv - float2(0, g_pixelSize.y)).r
);
const float a = 0.9;
float2 shift = (1 - a) * tan / (1 + a * tan * tan) * (c + 0.5);
float3 n = normalize(float3(tan, 1));
float3 l = normalize(float3(-0.1, 0.1, 1));
float d = dot(n, l);
return g_texture0.Sample(g_sampler0, input.uv + shift) * (d + 0.7 / (exp(-1000 * (d - 0.993)) + 1));
}
# include <Siv3D.hpp> // Siv3D v0.6.12
void Main()
{
const PixelShader wavePropagatePS = HLSL{ U"wave_propagate.hlsl", U"PS" };
if (not wavePropagatePS)
{
throw Error{ U"Failed to load a shader file" };
}
const PixelShader fluctuationPS = HLSL{ U"fluctuation.hlsl", U"PS" };
if (not fluctuationPS)
{
throw Error{ U"Failed to load a shader file" };
}
int32 oneSide = 15;
Texture windmill{ U"example/windmill.png" };
Size adaptiveSize = windmill.size() * 2;
Size FieldSize = adaptiveSize / oneSide;
const ConstantBuffer<Float2> cb{ Float2{ 1.0f, 1.0f } / FieldSize };
RenderTexture renderTexturePre{ FieldSize,ColorF(0.5),TextureFormat::R32_Float};
RenderTexture renderTextureNow{ FieldSize,ColorF(0.5),TextureFormat::R32_Float };
RenderTexture renderTextureNext{ FieldSize,TextureFormat::R32_Float };
RenderTexture renderTextureScene{ adaptiveSize };
Texture brushTexture{ U"example/particle.png" };
double accumTime = 0.0;
constexpr double dt = 1.0 / 100;
while (System::Update())
{
{
//drop water
if (MouseL.down())
{
const Vec2 pos = Cursor::PosF() / oneSide;
const ScopedRenderStates2D blend{ BlendState::Additive };
const ScopedRenderTarget2D target{ renderTexturePre };
brushTexture.scaled(0.3).drawAt(pos, ColorF(0.2));
const ScopedRenderTarget2D target2{ renderTextureNow };
brushTexture.scaled(0.3).drawAt(pos, ColorF(0.2));
}
//linear interpolation
{
const ScopedRenderTarget2D target{ renderTextureScene };
renderTextureNow.scaled(oneSide).draw();
}
//draw to screen
if(KeyN.pressed()){
const ScopedRenderStates2D blend{ SamplerState::ClampNearest };
renderTextureNow.scaled(oneSide).draw();
}
else{
Graphics2D::SetPSConstantBuffer(1, cb);
Graphics2D::SetPSTexture(1, renderTextureScene);
const ScopedCustomShader2D shader{ fluctuationPS };
windmill.scaled(2).draw();
}
}
//update wave
if (not KeySpace.pressed()) {
for (accumTime += Scene::DeltaTime(); accumTime > dt; accumTime -= dt) {
Graphics2D::SetPSConstantBuffer(1, cb);
Graphics2D::SetPSTexture(1, renderTexturePre);
const ScopedCustomShader2D shader{ wavePropagatePS };
const ScopedRenderTarget2D target{ renderTextureNext };
renderTextureNow.draw();
std::swap(renderTexturePre, renderTextureNow);
std::swap(renderTextureNow, renderTextureNext);
}
}
}
}
//
// Textures
//
Texture2D g_texture0 : register(t0);
Texture2D g_texture1 : register(t1);
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 PixelSize : register(b1)
{
float2 g_pixelSize;
}
static const float2 offsets[4] =
{
float2(0, -1),
float2(-1, 0),
float2(1, 0),
float2(0, 1),
};
float4 PS(s3d::PSInput input) : SV_TARGET
{
float c = g_texture0.Sample(g_sampler0, input.uv).r;
float pre = g_texture1.Sample(g_sampler0, input.uv).r;
float n = -4 * c;
for (uint i = 0; i < 4; ++i)
{
n += g_texture0.Sample(g_sampler0, input.uv + offsets[i] * g_pixelSize).r;
}
float r = c + 0.995 * (c - pre) + 0.1 * n;
return float4(r, r, r, 1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment