Пользователь
- Статус
- Оффлайн
- Регистрация
- 3 Янв 2020
- Сообщения
- 153
- Реакции
- 164
hey guys
I was working on a new menu and experimenting with adding noise to my menu, and I figured I’d share my approach and code so you can try it out too.
Instead of using a noise texture, I implemented a simple procedural noise directly in the pixel shader. It’s lightweight and customizable
here the pixel shader i used to generate the noise and apply it conditionally
so we need setup our noise buffer to send noise parameters:
now we need add this to our dx11 adapter to update and bind the constant buffer if noise is enabled
we also need add these to our commands so we can control the stuff we need
now we just need add this to our functions and adjust them
that should be everything you need, You can adjust the noise scale and amount to get the look you want your free to customize the shader noise function if you want different patterns or more complexity.
I was working on a new menu and experimenting with adding noise to my menu, and I figured I’d share my approach and code so you can try it out too.
Instead of using a noise texture, I implemented a simple procedural noise directly in the pixel shader. It’s lightweight and customizable
here the pixel shader i used to generate the noise and apply it conditionally
C++:
const char* pixel_shader_code = R"(
cbuffer PanelParams : register(b1)
{
float NoiseScale; // >0 enables noise (used as scale)
float NoiseAmount; // noise strength
float UseNoise; // 0=no noise, 1=apply
float _Pad;
}
struct PS_INPUT {
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
SamplerState sampler0 : register(s0);
Texture2D texture0 : register(t0);
float hash(float2 p) {
p = frac(p * 0.3183099 + 0.1);
p *= 17.0;
return frac(p.x * p.y * (p.x + p.y));
}
float noise2D(float2 uv) {
float2 i = floor(uv);
float2 f = frac(uv);
float2 u = f*f*(3.0-2.0*f);
float a = hash(i + float2(0,0));
float b = hash(i + float2(1,0));
float c = hash(i + float2(0,1));
float d = hash(i + float2(1,1));
return lerp(lerp(a,b,u.x), lerp(c,d,u.x), u.y);
}
float4 main(PS_INPUT input) : SV_Target {
float4 tex = texture0.Sample(sampler0, input.uv);
float4 out_col = input.col * tex;
if (UseNoise > 0.5) {
float n = noise2D(input.uv * NoiseScale);
out_col.rgb = saturate(out_col.rgb + (n - 0.5) * 2.0 * NoiseAmount);
}
return out_col;
}
)";
so we need setup our noise buffer to send noise parameters:
C++:
// Panel noise params constant buffer (NoiseScale, NoiseAmount)
{
D3D11_BUFFER_DESC desc = {};
desc.ByteWidth = sizeof(float) * 4; // 16 bytes aligned
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
if (FAILED(device->CreateBuffer(&desc, nullptr, &panel_params_cb))) {
REN_DBG("Failed to create panel params constant buffer");
return;
}
}
now we need add this to our dx11 adapter to update and bind the constant buffer if noise is enabled
C++:
if (cmd.use_panel_noise) {
D3D11_MAPPED_SUBRESOURCE mapped_resource;
if (SUCCEEDED(ctx->Map(panel_params_cb, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource))) {
float* p = reinterpret_cast<float*>(mapped_resource.pData);
p[0] = cmd.noise_scale; // NoiseScale
p[1] = cmd.noise_amount; // NoiseAmount
p[2] = 1.0f;
p[3] = 0.0f;
ctx->Unmap(panel_params_cb, 0);
}
ctx->PSSetConstantBuffers(1, 1, &panel_params_cb);
}
else {
ID3D11Buffer* nullCB = nullptr;
ctx->PSSetConstantBuffers(1, 1, &nullCB);
}
we also need add these to our commands so we can control the stuff we need
C++:
float noise_scale; // 0 = no noise
float noise_amount; // strength 0.05 good
bool use_panel_noise;
now we just need add this to our functions and adjust them
C++:
if (enable_noise) {
g.use_panel_noise = true;
g.noise_scale = scale;
g.noise_amount = strength;
}
that should be everything you need, You can adjust the noise scale and amount to get the look you want your free to customize the shader noise function if you want different patterns or more complexity.