Created
February 22, 2024 17:50
-
-
Save comefrombottom/e8e4d2b9e8cbb87cc54489cc9cb9e551 to your computer and use it in GitHub Desktop.
水面の揺らぎをシェーダで作ってみた。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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