09-29-2023, 01:21 PM
First I need to say that using Vulkan is much more complicated than using DirectX (or OpenGL).
To create a custom shader you would first need to create a custom Effect (derive you effect from Effect class). This effect needs to override the ApplyRenderingItemMaterial method - there the Vulkan buffers, Pipelines and other data are set to the RenderingItem object (based on the data from the material). Also, the RenderingItem.EffectTechnique needs to be set - the EffectTechnique.Render method is called when rendering the RenderingItem in the RenderObjectsRenderingStep (FillCommandBufferRenderingStep). The EffectTechnique can be set to the StandardEffectTechnique or to your own EffectTechnique that provides your own implementation of the Render method.
If you need to provide some custom material information, then you also need to create a custom Material (derived from Material class). If you can reuse any existing material (for example StandardMaterial, VertexColorMaterial, etc.) then you only need to set the Material.Effect property to your custom effect.
This is a very short description on how to implement your own effect. As you may see, this may be quite complicated. So I would currently not recommend you to try to create your own effect.
Because all work is currently devoted to preparing the first production ready version, I do not have time to provide a sample and a document that would describe how to prepare a custom effect. This will surely be done sometime in the future.
What is more, if you want to efficiently render large height maps, then this cannot be done by just a simple custom effect. You would need to define an effect that would generate the mesh on the GPU. And this would make this even more complicated.
So I would recommend you to try to use what is available:
To render a height map with a hard gradient, you can use a one dimensional gradient texture (the color at position 0 defines the color for min value; the last position defines the color for max value).
You can create such texture by calling TextureFactory.CreateGradientTexture, for example:
To create hard gradient define sharp gradient stops - see AdvancedHeightMapSample.
In the next beta version it will also be possible to disable color interpolation by using the new ClampNoInterpolation sampler type (this can then be used instead of Clamp sampler that is passed to the StandardMaterial constructor).
Then the texture coordinates are defined to point to the correct color for the height value at the specific position, for example texture coordinate (0, 0.5) is set the minimum height value and texture coordinate (1, 0.5) is set to the maximum height value.
When using the height map objects from SharpEngine, you can define the mesh with texture coordinates as height values by calling constructor of HeightMapSurfaceNode and setting the useHeightValuesAsTextureCoordinates to true.
But if you do not want to use HeightMapSurfaceNode, then you can also update your mesh by setting the texture coordinates so that they will be based on the height data - from (0, 0.5) to (1, 0.5) as described before.
To create a custom shader you would first need to create a custom Effect (derive you effect from Effect class). This effect needs to override the ApplyRenderingItemMaterial method - there the Vulkan buffers, Pipelines and other data are set to the RenderingItem object (based on the data from the material). Also, the RenderingItem.EffectTechnique needs to be set - the EffectTechnique.Render method is called when rendering the RenderingItem in the RenderObjectsRenderingStep (FillCommandBufferRenderingStep). The EffectTechnique can be set to the StandardEffectTechnique or to your own EffectTechnique that provides your own implementation of the Render method.
If you need to provide some custom material information, then you also need to create a custom Material (derived from Material class). If you can reuse any existing material (for example StandardMaterial, VertexColorMaterial, etc.) then you only need to set the Material.Effect property to your custom effect.
This is a very short description on how to implement your own effect. As you may see, this may be quite complicated. So I would currently not recommend you to try to create your own effect.
Because all work is currently devoted to preparing the first production ready version, I do not have time to provide a sample and a document that would describe how to prepare a custom effect. This will surely be done sometime in the future.
What is more, if you want to efficiently render large height maps, then this cannot be done by just a simple custom effect. You would need to define an effect that would generate the mesh on the GPU. And this would make this even more complicated.
So I would recommend you to try to use what is available:
To render a height map with a hard gradient, you can use a one dimensional gradient texture (the color at position 0 defines the color for min value; the last position defines the color for max value).
You can create such texture by calling TextureFactory.CreateGradientTexture, for example:
Code:
var gradientData = new GradientStop[]
{
new GradientStop(Colors.White, 1.0f),
new GradientStop(Colors.White, 0.8f),
new GradientStop(Colors.LightGreen, 0.799f),
new GradientStop(Colors.LightGreen, 0.3f),
new GradientStop(Colors.Blue, 0.299f),
new GradientStop(Colors.Blue, 0.0f)
};
// Create 1D texture; "linear" texture that requires special texture coordinates
var gradientTexture = TextureFactory.CreateGradientTexture(GpuDevice, gradientData, textureWidth: 256);To create hard gradient define sharp gradient stops - see AdvancedHeightMapSample.
In the next beta version it will also be possible to disable color interpolation by using the new ClampNoInterpolation sampler type (this can then be used instead of Clamp sampler that is passed to the StandardMaterial constructor).
Then the texture coordinates are defined to point to the correct color for the height value at the specific position, for example texture coordinate (0, 0.5) is set the minimum height value and texture coordinate (1, 0.5) is set to the maximum height value.
When using the height map objects from SharpEngine, you can define the mesh with texture coordinates as height values by calling constructor of HeightMapSurfaceNode and setting the useHeightValuesAsTextureCoordinates to true.
But if you do not want to use HeightMapSurfaceNode, then you can also update your mesh by setting the texture coordinates so that they will be based on the height data - from (0, 0.5) to (1, 0.5) as described before.
Andrej Benedik

