I have made a material for ocean waves where I have a custom block which calculates the wave height and normal based on the sum of sines calculation (It has to be sum of sines, not gerstner, as I have a separate physics engine that relies on the sum of sines which cannot be changed, and I am just using unreal to visualise the physics engine). The custom block code looks like:
int numWaves = MaterialCollection0.Vectors[0][0];
float sum = 0.0f;
Normal = float3(0.0f,0.0f,0.0f);
int numParams = 5;
for (int i=0; i<36; i++)
{
//int i=1;
int wave = i;
float offset = 1.0 + (wave *numParams);
float a = MaterialCollection0.Vectors[(offset + 0)* 0.25][(offset + 0)%4];
float omega = MaterialCollection0.Vectors[(offset + 1)* 0.25][(offset + 1)%4];
float k1 = MaterialCollection0.Vectors[(offset + 2)* 0.25][(offset + 2)%4];
float k2 = MaterialCollection0.Vectors[(offset + 3)* 0.25][(offset + 3)%4];
float phase = MaterialCollection0.Vectors[(offset + 4)* 0.25][(offset + 4)%4];
float theta = omega * Time + k1 * PosX + k2 * PosY + phase;
float z = a * (cos(theta) + 0.2f * cos(2.0f * theta));
sum += z;
// Add derivative
float msinc = -sin(theta);
float dx = a*k1 * msinc;
float dy = a*k2 * msinc;
Normal += float3(-dx, dy, 0.0);
// --- Add secondary wave component ---
float theta2 = 2.0*theta;
float a2 = a*0.2f;
float msinc2 = -sin(theta2);
float dx2 = a2*k1 * msinc2;
float dy2 = a2*k2 * msinc2;
Normal += float3(-dx2, dy2, 0.0);
}
Normal.z = 1.0;
return sum;
I have got this to work by using a material collection where I set variables, however the material collection can only be a vector of length 4 vectors, whereas in my calculation the waves are defined with 5 parameters.
I want to try and make my own custom shader where I have a buffer with a struct like:
struct WaveParameter {
float a;
float omega;
float k1;
float k2;
float phase;
}
So that I can get around the weird indexing of the material collection, to hopefully try and get some performance improvement.
I have managed to get some
knowledge of shaders in unreal following these tutorials:
https://itscai.us/blog/post/ue-view-extensions/#step-1-setting-up-your-unreal-project
and
However none of these completely do what I want to do (and the last one, I am not sure how to do the last stage).
To learn how to do what I want to do, I want to make a simple shader like:
float4 color;
float4 GetColor()
{
return color;
}
And then just be able to set the value of the color during the games run time.
I think I need to do this eventually by doing something like:
class FOO_API FSomeShaderPS : public FGlobalShader {
DECLARE_GLOBAL_SHADER(FSomeShaderPS);
FSomeShaderPS () {}
FSomeShaderPS (const ShaderMetaType::CompiledShaderInitializerType& Initializer) : FGlobalShader(Initializer) {
MyColorParameter.Bind(Initializer.ParameterMap, TEXT("MyColor"), SPF_Mandatory);
}
template<typename TShaderRHIParamRef>
static void SetColor(FRHICommandListImmediate& RHICmdList, const TShaderRHIParamRef ShaderRHI, FLinearColor Color) {
SetShaderValue(RHICmdList, ShaderRHI, MyColorParameter, Color);
}
private:
LAYOUT_FIELD(FShaderParameter, MyColorParameter);
}
And then be able to call SetColor
somehow.
Am I anywhere close to correct? Are there any other good tutorials where I can learn to be able to do this?
Any help would be appreciated. Thanks