Replies: 3 comments 7 replies
-
would the
e.g. #[derive(Default, Resource, Debug, Clone)]
pub struct DynamicShaderMaterial(Handle<Shader>);
impl Material for DynamicShaderMaterial {
fn specialize(
_pipeline: &MaterialPipeline<Self>,
descriptor: &mut RenderPipelineDescriptor,
_layout: &MeshVertexBufferLayoutRef,
_key: MaterialPipelineKey<Self>,
) -> Result<(), SpecializedMeshPipelineError> {
descriptor.vertex.shader = self.0.clone();
descriptor.fragment.as_mut().unwrap().shader = self.0.clone();
Ok(())
}
} |
Beta Was this translation helpful? Give feedback.
-
Do you need to be able to update the bindings dynamically too or only the fragment/vertex shader with fixed material bindings? If you don't need to update the bindings at runtime I'm not entirely sure I understand why you can't just store the shader handle in a const associated with a material that uses that const? |
Beta Was this translation helpful? Give feedback.
-
This example should have what you need for a custom 3d pipeline. https://github.com/bevyengine/bevy/blob/main/examples/shader/custom_phase_item.rs |
Beta Was this translation helpful? Give feedback.
-
I'm attempting to solve a difficult problem and I need help. The use case is an app that interactively generates shaders, such as ShaderToy or Blender's shader editor. I already have code that can procedurally generate the .wgsl source and generate a
Handle<Shader>
. However, now I want to preview what the shader looks like on a Bevy primitive such asSphere
orCuboid
.Ideally, what I want is something that behaves mostly like
StandardMaterial
, except with the vertex shader replaced with my generated shader. In this sense, it's much likeExtendedMaterial
, except that won't work in this case because Bevy materials are (mostly) stateless: thefragment_shader()
andvertex_shader()
methods have noself
param, they can only return static constants.Also, because I want to be able to preview multiple materials at the same time, the shader can't be a static global or a handle in a resource. Similarly, writing out the shader code to a file and then loading the file as an asset doesn't work either, since the asset path to the file would have to be dynamic too.
From what I can tell, the only solution is to create a custom render pipeline. There are only a tiny number of examples on the web showing how to set up a pipeline in Bevy: two official examples, the one in Hanabi, and one older message board post from the Bevy 0.11 era.
Most of these examples are somewhat problematic because they set up a pipeline from scratch: that is, they don't leverage much of the functionality of the existing pipelines. This makes sense for something like Hanabi, which is creating a new type of primitive (particles) that doesn't overlap much with the existing Bevy primitives. I would much rather be able to invoke the standard mesh pipeline and then tweak the output - this means that I wouldn't have to duplicate all the complex logic around MSAA, buffer layouts, vertex formats, and so on. Also, a lot of these examples omit details for clarity - like for example always using the MSAA default setting instead of the "real" value.
The one example that sort of does what I want is the
mesh2d_manual
example: it uses the standard mesh2d pipeline to create aRenderPipelineDescriptor
and then modifies some of the properties afterwards. Unfortunately, the 2d pipelines are just different enough from the 3d pipelines (in terms of how things are constructed) that I have been unable to figure out how to adapt this same approach to 3d rendering.So basically I need an example showing how to do this.
I should mention, BTW, that the work I'm doing is part of porting one of my apps from three.js to Bevy, and generating shader code algorithmically and assigning it to a material is fairly trivial to do in three.js.
Beta Was this translation helpful? Give feedback.
All reactions