Next, I want to update the shader from the program by adjusting
the tint color. This is done by defining a constant buffer
in the shader and then transferring a copy from the CPU to the GPU
inside the PrepareForRender() function.
The use of the word "constants" here is misleading -- the values
are constant only from the perspective of the shader code.
From the CPU perspective, the whole point of the constants buffer is
to dynamically modify the behavior of the shader at
runtime.
Add a CONSTANTS buffer to the Shader
My constant buffer will contain a single value, a COLOR that
will be added to each pixel. Add this to the shader hlsl code:
Shader tint:
#define D2D_INPUT_COUNT 1 // The pixel shader takes 1 input texture.
#define D2D_INPUT0_COMPLEX // The first input is sampled in a complex manner: to calculate the output of a pixel,
// the shader samples more than just the corresponding input coordinate.
#define D2D_REQUIRES_SCENE_POSITION // The pixel shader requires the SCENE_POSITION input.
// Note that the custom build step must provide the correct path to find d2d1effecthelpers.hlsli when calling fxc.exe.
#include "d2d1effecthelpers.hlsli"
cbuffer constants: register(b0) {
float4 tint:COLOR;
};
D2D_PS_ENTRY(main) {
float2 toPixel = D2DGetScenePosition().xy;
// Scale distance to account for screen DPI, and such that the ripple's displacement
// decays to 0 at a hardcoded limit of 500 DIPs.
float distance = length(toPixel / 500.0f);
float2 direction = normalize(toPixel);
// Resample the image based on the new coordinates.
float4 color = D2DSampleInputAtOffset(0, direction);
color+= tint;
return color;
}
//EOF: FIRSTSHADER.HLSL
Constants cannot be initialized or updated in the hlsl, they must
be updated from the CPU? What does "register(b0)" mean? What is
register b0?
Microsoft:
HLSL uses virtual registers that the code can use to provide
optimization hints to the compiler. These registers are broken
into four functional spaces:
t: Shader resource views (SRV) (textures)
s: Samples
u: Unordered access views (UAV)
b: Constant buffers (CBV) (parameters)
Add the Constants to the Effect
I need to keep a mirror image of the constants buffer in the
effect on the cpu. Add this to MyEffect:
I should now see a blue tint on the bouncing ball.
Changing the Constants
Now I need to update the tint color from the CPU. Since DirectX
is managing the effect, I need to go through the ID2D1Effect interface.
This adds some extra steps:
Create GetTint() and SetTint() functions.
Add the functions to the Bindings in RegisterEffectFromString()
Update the Effect XML to describe the Tint property.
The GetTint() and SetTint() functions are straight-forward, except
that I want to manage the tint color as a UINT32 on the CPU and as a
float4 on the GPU. So I will need to convert between UINT32 and
float4.
Finally, in my MsgTimer() function I will update the Tint to a random
color every 30ms. Note that rand() returns a 16bit value, so I use two
to form a 32bit RGBA color.
Now I should see the ball covered by a random, flickering tint.
Sharp eyes might notice something odd: I am setting Tint to a
random 32bit value, which includes the alpha channel. I would expect
the ball to flicker in brightness, tending toward very dim since most
of the random alpha values would result in blending the black
background. This is clearly not the case, the ball flickers in color
but is vivid. Why?
My pixel shader is now running in place of the normal alpha
blender, and I am ignoring the alpha value. If I wanted the alpha to
be applied, I would need to perform the multiplication explicitly.
Add a Second Parameter
Bright will be a second parameter that will control the
overall brightness (0.0 to 1.0) of all non-black pixels.
Add float bright to the Constants struct.
Add SetBright() and GetBright() to MyEffect.
Add float bright to the shader cbuffer.
Add the Bright property to the Register XML and Bindings array.
Add the Bright property to the Register XML and Bindings. Be careful
here, as any typo in the XML will not be caught by the compiler but will
cause the Register() to fail with "0x80070057: The parameter is incorrect."
Comments are moderated. Anonymous comments are not visible
to others until moderated. Comments are owned by the author but may be
removed or reused (but not modified) by this site at any time without notice.