![]() |
|
Adding a Shader to a ModelVisual3D - Printable Version +- AB4D Forum (https://forum.ab4d.com) +-- Forum: Products Forums (https://forum.ab4d.com/forumdisplay.php?fid=4) +--- Forum: Ab3d.DXEngine (https://forum.ab4d.com/forumdisplay.php?fid=11) +--- Thread: Adding a Shader to a ModelVisual3D (/showthread.php?tid=4011) |
Adding a Shader to a ModelVisual3D - leonardo - 05-02-2017 Hello, I am evaluating AB4D to improve my WPF 3D application. I want to apply a custom vertex/pixel shader to my ModelVisual3D that contain my 3d model (not all scene). Is there a simple way to do it? Thank you Leonardo RE: Adding a Shader to a ModelVisual3D - abenedik - 05-03-2017 Ab3d.DXEngine support using custom shaders that are used to render some 3D objects. When I wanted to answer your question, I have found out that there is no good sample on how to on how to create a custom material that uses custom shader and can have different property values for different models. There are a few sample on how to use custom shaders (for example Customizations/CustomFogShaderEffectSample in the main DXEngine samples project and the ShaderFactory project) but they only use standard material properties or have some global properties (fog settings). Because good customizability is one of the major features of DXEngine and because support for custom shaders is needed for that, I have decided to write a new sample that will show how to create a custom material that use custom effect with custom shaders. I have updated the samples in the evaluation and commercial versions. For those how already have that installed, you can download the zip that is attached to this post and add and overwrite the files from zip over the existing sample files. The proces of using custom shaders is best described in the sample, but you can also follow the following guide: To use custom shaders, you first need to prepare the custom Effect and custom Material classes. Custom effect class is created by deriving a new class from Ab3d.DirectX.Effect - effect defines how a material that uses this effect will be rendered. Then you need to override the following methods: OnInitializeResources (create shaders and other resources), OnApplyPerFrameSettings, ApplyMaterial (setup per-frame and per-object resources), Dispose. To store the custom material properties that are different for each 3D model, you also need to create a custom Material class - a new class that is derived from Ab3d.DirectX.Material - this class can also implement some standard material interfaces (see what is available in the Ab3d.DirectX.Materials namespace). You can also define your own interface and define your custom properties there. This material object is then passed to the ApplyMaterial method in your Effect class - there you can read your custom material properties and set the shader constant buffers accordingly. To tell DXEngine to use your custom effect to render your custom material you need to set the material's Effect property to an instance of your effect. The best way to do this is in material's overridden OnInitializeResources method. Here you set the Effect property to an instance of your custom effect. Here you can also register your custom effect. The following code does this: Code: /// <summary>As you see from code comments, the GetEffect method is used to get an instance of MyEffect. This also registers and creates an instance of MyEffect on EffectsManager. If you need to have more control over the creation of MyEffect instance, you can use the following code (calling GetEffect with createNewEffectInstanceIfNotFound parameter set to false): Code: /// <summary>Another option is to register your effect in the DXEngine initialization process: Code: MainDXViewportView.DXSceneDeviceCreated += delegate(object sender, EventArgs args)Here the DXSceneDeviceCreated event is used to execute the code after the DXDevice is created. You also need to override the Dispose method where you dispose the Effect: Code: protected override void Dispose(bool disposing)Now you can create your 3D objects and assign your custom material to the objects. To do this, you need to assign an instance of your custom material to a WPF material that is used by 3D object - for example: Code: var myCustomDXMaterial = new MyCustomDXMaterial()(I am planning to simplify this in the future so you will not need to create a WPF material and will be able to assign your material directly to the GeometryModel3D). An even better picture of how shaders are used in DXEngine can be get with purchasing "Effects source code" for $299 - this will give you fill source code of all hlsl files and Effect files used in DXEngine. RE: Adding a Shader to a ModelVisual3D - leonardo - 05-04-2017 Thank you very much Andrej. I am studying the new sample. Leonardo RE: Adding a Shader to a ModelVisual3D - leonardo - 05-11-2017 I have understood your example, but I am thinking to simpler API. Any change to have a Material like this? <ShaderMaterial PixelShader="mypixelshader.hlsl" VertexShader="myvertexshader.hlsl" /> With automatic shader compilation/caching and a way to pass parameters of Shaders with Data Binding from XAML? Thank you Leonardo RE: Adding a Shader to a ModelVisual3D - abenedik - 05-11-2017 I agree that it would be great to have such simple way to define new materials. But because shaders are usually not defined very often, I think that it is worth investing a little bit more time to provide a fixed Effect and fixed Material implementation (instead of having a dynamic shader and material). After that your application will be able to benefit from the the following advantages:
objects, then the code that sets up material is performance critical - ideally it is called 60 times per second for each object and for each material property. But because one of the main purpose of Ab3d.DXEngine is to provide easy to use access to DirectX 11, I am planning to write a sample that will show how to use DirectX 11 Effects framework - this provides a way to have a more dynamic-like access to shader properties. I currently do not have time to do that but have that quite high on my DXEngine todo list. You may also check some other opinion on advantages and disadvantages of using a more dynamic approach (with Effects library) vs. static approach (standard constant buffers) on the following discussion: https://gamedev.stackexchange.com/questions/40643/directx-11-constant-buffers-vs-effect-framework |