Skip to content

Instantly share code, notes, and snippets.

@saint11
Created June 27, 2023 22:58
Show Gist options
  • Save saint11/8174e076c83e1f4b460b0b70d7644e9e to your computer and use it in GitHub Desktop.
Save saint11/8174e076c83e1f4b460b0b70d7644e9e to your computer and use it in GitHub Desktop.
Masking and distortion shader for pixel art water reflection
//-----------------------------------------------------------------------------
// Defines (so this compiles for PS4 or XNA)
//-----------------------------------------------------------------------------
// PS4
#if __PSSL__
#define DECLARE_TEXTURE(name, index) \
Texture2D name : register(t##index); \
SamplerState name##Sampler : register(s##index)
#define SAMPLE_TEXTURE(Name, texCoord) Name.Sample(Name##Sampler, texCoord)
#define PS_3_SHADER_COMPILER sce_ps_orbis
#define PS_2_SHADER_COMPILER sce_ps_orbis
#define VS_SHADER_COMPILER sce_vs_vs_orbis
#define SV_TARGET0 S_TARGET_OUTPUT0
#define SV_TARGET1 S_TARGET_OUTPUT1
#define SV_TARGET2 S_TARGET_OUTPUT2
#define SV_Position S_POSITION
#elif XBOXONE
#define DECLARE_TEXTURE(name, index) \
Texture2D<float4> name : register(t##index); \
sampler name##__XBSAMP : register(s##index)
#define SAMPLE_TEXTURE(name, texCoord) name.Sample(name##__XBSAMP, texCoord)
#define PS_3_SHADER_COMPILER ps_5_0
#define PS_2_SHADER_COMPILER ps_5_0
#define VS_SHADER_COMPILER vs_5_0
// XNA / DirectX 11
#else
#define DECLARE_TEXTURE(Name, index) \
texture Name: register(t##index); \
sampler Name##Sampler: register(s##index)
#define SAMPLE_TEXTURE(Name, texCoord) tex2D(Name##Sampler, texCoord)
#define PS_3_SHADER_COMPILER ps_3_0
#define PS_2_SHADER_COMPILER ps_2_0
#define VS_SHADER_COMPILER vs_3_0
#define VS_2_SHADER_COMPILER vs_2_0
#define SV_TARGET0 COLOR0
#define SV_TARGET1 COLOR1
#define SV_TARGET2 COLOR2
#endif
// Based on https://www.shadertoy.com/view/MdlXz8
#include "Common.fxh"
#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0
#define PS_SHADERMODEL ps_4_0
#endif
#define TAU 6.28318530718
#define MAX_ITER 5
float Time;
float RippleFrequency;
float RippleAmplitude;
float2 TextureSize;
float4x4 MatrixTransform;
float4x4 CameraOffset;
sampler inputTexture;
DECLARE_TEXTURE(mask, 1)
{
AddressU =
Clamp;
AddressV = Clamp;
MinFilter =
Point;
MagFilter = Point;
MipFilter =
Point;
};
float Map(float value, float min1, float max1, float min2, float max2)
{
// Convert the current value to a percentage
// 0% - min1, 100% - max1
float perc = (value - min1) / (max1 - min1);
// Do the same operation backwards with min2 and max2
value = perc * (max2 - min2) + min2;
return value;
}
// THis goes out of your Vertex Shader into your Pixel Shader
struct VSOutput
{
float4 position : SV_Position;
float2 texCoord0 : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
float4 color : COLOR0;
};
VSOutput SpriteVertexShader(
float4 position : POSITION0,
float2 texCoord0 : TEXCOORD0,
float4 color : COLOR0)
{
VSOutput output;
output.position = mul(position, MatrixTransform);
output.worldPosition = mul(position, CameraOffset);
output.texCoord0 = texCoord0;
output.color = color;
return output;
}
float4 SpritePixelShader(VSOutput input) : SV_Target0
{
float4 mask = SAMPLE_TEXTURE(mask, input.texCoord0);
// Calculate the texture coordinates based on the world position
float2 texCoord = (input.worldPosition.xy * 4) / TextureSize;
float2 p = fmod(texCoord * TAU, TAU) - 250.0;
float2 i = float2(p);
float c = 1.0;
float inten = .005;
for (int n = 0; n < MAX_ITER; n++)
{
float t = (Time * 0.2) * (1.0 - (3.5 / float(n + 1)));
i = p + float2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
c += 1.0 / length(float2(p.x / (sin(i.x + t) / inten), p.y / (cos(i.y + t) / inten)));
}
c /= float(MAX_ITER);
c = 1.17 - pow(c, 1.4);
float wave = pow(abs(c), 8.0) - 1;
float edge = Map(wave, -2.5, 1, -0.5, 0.5);
float2 samplePosition = input.texCoord0 + edge * 0.015 * float2(2.5, 1);
float4 sampled = tex2D(inputTexture, samplePosition);
float edgeColor = 0.15;
sampled = lerp(float4(edgeColor, edgeColor, edgeColor, 1), sampled, SAMPLE_TEXTURE(mask, samplePosition).r);
float4 color = lerp(sampled, float4(wave, wave, wave, 1), 0.015);
return lerp(float4(0, 0, 0, 0), color, mask.r);
}
technique Simple
{
pass Pass1
{
PixelShader = compile PS_SHADERMODEL SpritePixelShader();
VertexShader = compile VS_SHADERMODEL SpriteVertexShader();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment