Closed ghost closed 1 year ago
Ok seems like the custom render pass is for post process effects ? I have at least found a way to get a minimal working example, although I'm not sure why I had to transform the quad and texture coordinates, nor how safe it is to grab the color attachment as I have done.
core::{
algebra::{Matrix4, Vector3, Vector4},
pool::Handle,
sstorage::ImmutableString
},
scene::{
Scene,
mesh::{
surface::{SurfaceData},
},
},
renderer::{
Renderer,
SceneRenderPass,
SceneRenderPassContext,
RenderPassStatistics,
framework::{
error::FrameworkError,
framebuffer::{DrawParameters},
gpu_program::{
GpuProgram,
UniformLocation
},
geometry_buffer::{
GeometryBuffer,
GeometryBufferKind
}
}
},
utils::log::Log
};
use std::rc::Rc;
use std::cell::RefCell;
pub struct MyRenderPass {
enabled: bool,
shader: GpuProgram,
target_scene: Handle<Scene>,
quad: GeometryBuffer,
world_view_projection: UniformLocation,
color_sampler: UniformLocation
}
impl MyRenderPass {
pub fn new(
renderer: &mut Renderer,
target_scene: Handle<Scene>,
) -> Result<Self, FrameworkError> {
let vs = r#"
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexTexCoord;
uniform mat4 worldViewProjection;
out vec2 texCoord;
void main()
{
texCoord = 1.0 - vertexTexCoord;
gl_Position = worldViewProjection * vec4(vertexPosition, 1.0);
}
"#;
let fs = r#"
in vec2 texCoord;
out vec4 FragColor;
uniform sampler2D colorSampler;
void main()
{
FragColor = texture(colorSampler, texCoord) * vec4(1.5, 1.0, 1.0, 1.0);
}
"#;
let shader = GpuProgram::from_source(&mut renderer.state, "MyShader", vs, fs)?;
Ok(Self {
enabled: true,
world_view_projection: shader.uniform_location(
&renderer.state,
&ImmutableString::new("worldViewProjection"),
)?,
color_sampler: shader.uniform_location(
&renderer.state,
&ImmutableString::new("colorSampler"),
)?,
target_scene,
quad: GeometryBuffer::from_surface_data(
&SurfaceData::make_quad(&Matrix4::new_translation(&Vector3::new(0.5, 0.5, 0.0))),
GeometryBufferKind::StaticDraw,
&mut renderer.state,
),
shader,
})
}
}
impl SceneRenderPass for MyRenderPass {
fn on_ldr_render(
&mut self,
ctx: SceneRenderPassContext,
) -> Result<RenderPassStatistics, FrameworkError> {
let mut stats = RenderPassStatistics::default();
// Make sure to render only to target scene.
if self.enabled && ctx.scene_handle == self.target_scene {
let frame_matrix = Matrix4::new_orthographic(
0.0,
ctx.viewport.w() as f32,
ctx.viewport.h() as f32,
0.0,
-1.0,
1.0,
) * Matrix4::new_nonuniform_scaling(&Vector3::new(
ctx.viewport.w() as f32,
ctx.viewport.h() as f32,
0.0,
));
let screen_texture = ctx.framebuffer.color_attachments()[0].texture.clone();
stats += ctx.framebuffer.draw(
&self.quad,
ctx.pipeline_state,
ctx.viewport,
&self.shader,
&DrawParameters::default(),
|mut program| {
program.set_matrix4(&self.world_view_projection, &frame_matrix);
program.set_texture(&self.color_sampler, &screen_texture);
},
);
}
Ok(stats)
}
}
pub fn setup(renderer: &mut Renderer, render_pass: MyRenderPass) {
let shared_pass = Rc::new(RefCell::new(render_pass));
// You can share the pass across multiple places to be able to control it.
renderer.add_render_pass(shared_pass);
}
Custom render passes allows you to render anything you want to, however it does not auto-magically applied to scene nodes. You need to implement drawing manually for them. One of the main usages of custom render passes is post effects, yes. You might be interested in shaders and materials if you want to apply custom effects to meshes.
Somehow I overlooked the fact that pbr is supported by default, that'll save some effort.
Hi,
I have followed the documentation example (with minor changes in vertex shader due to shader compilation issues) and I expect the result to be a scene rendered in red, however I see no change. Is there a missing step ?
I have a scene setup with a camera which renders as I expect it to. The setup() function below is called and the render pass appears to be added to the renderer.