Skip to content

Commit

Permalink
Improve camera API (#392)
Browse files Browse the repository at this point in the history
* Rename

* disable_tone_and_color_mapping + set_default_tone_and_color_mapping

* FullScreenEffect

* Rename and docs

* Fix ids
  • Loading branch information
asny committed Aug 9, 2023
1 parent 6c9ce24 commit ac8aedc
Show file tree
Hide file tree
Showing 18 changed files with 170 additions and 67 deletions.
9 changes: 3 additions & 6 deletions examples/fog/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ pub async fn run() {
Wrapping::ClampToEdge,
);
}
camera.tone_mapping = ToneMapping::None;
camera.target_color_space = ColorSpace::Compute;
camera.disable_tone_and_color_mapping();
RenderTarget::new(
color_texture.as_color_target(None),
depth_texture.as_depth_target(),
Expand All @@ -119,9 +118,7 @@ pub async fn run() {
change |= fog_enabled; // Always render if fog is enabled since it contain animation.

if change {
camera.tone_mapping = ToneMapping::default();
camera.target_color_space = ColorSpace::Srgb;

camera.set_default_tone_and_color_mapping();
if fog_enabled {
fog_effect.time = frame_input.accumulated_time as f32;
frame_input.screen().apply_screen_effect(
Expand All @@ -133,7 +130,7 @@ pub async fn run() {
);
} else {
frame_input.screen().apply_screen_effect(
&CopyEffect::default(),
&ScreenEffect::default(),
&camera,
&[],
Some(ColorTexture::Single(&color_texture)),
Expand Down
8 changes: 3 additions & 5 deletions examples/image/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pub async fn run() {
let context = window.gl();

let mut camera = Camera::new_2d(window.viewport());
camera.tone_mapping = ToneMapping::None;

// Source: https://polyhaven.com/
let mut loaded = if let Ok(loaded) =
Expand Down Expand Up @@ -100,20 +99,19 @@ pub async fn run() {
Wrapping::ClampToEdge,
);

camera.target_color_space = ColorSpace::Compute;
camera.tone_mapping = ToneMapping::None;
camera.disable_tone_and_color_mapping();
target
.as_color_target(None)
.clear(ClearState::default())
.apply_screen_material(&material, &camera, &[]);

camera.target_color_space = ColorSpace::Srgb;
camera.color_mapping = ColorMapping::default();
camera.tone_mapping = tone_mapping;
frame_input
.screen()
.clear(ClearState::default())
.apply_screen_effect(
&CopyEffect::default(),
&ScreenEffect::default(),
&camera,
&[],
Some(ColorTexture::Single(&target)),
Expand Down
6 changes: 0 additions & 6 deletions examples/multisample/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ pub fn main() {

window.render_loop(move |mut frame_input| {
camera.set_viewport(frame_input.viewport);
camera.tone_mapping = ToneMapping::default();
camera.target_color_space = ColorSpace::Srgb;

let mut panel_width = 0.0;
gui.update(
Expand Down Expand Up @@ -161,8 +159,6 @@ pub fn main() {
.clear(clear_state)
.render(&camera, renderable_things, &[]);

camera.tone_mapping = ToneMapping::None;
camera.target_color_space = ColorSpace::Compute;
frame_input.screen().apply_screen_effect(
&CopyEffect::default(),
&camera,
Expand All @@ -185,8 +181,6 @@ pub fn main() {
.render(&camera, renderable_things, &[])
.resolve_color();

camera.tone_mapping = ToneMapping::None;
camera.target_color_space = ColorSpace::Compute;
frame_input.screen().clear(clear_state).apply_screen_effect(
&CopyEffect::default(),
&camera,
Expand Down
8 changes: 3 additions & 5 deletions examples/terrain/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,7 @@ pub async fn run() {
water.animate(frame_input.accumulated_time as f32);

if change {
camera.tone_mapping = ToneMapping::None;
camera.target_color_space = ColorSpace::Compute;
camera.disable_tone_and_color_mapping();
if camera.viewport().width != color_texture.width()
|| camera.viewport().height != color_texture.height()
{
Expand Down Expand Up @@ -270,12 +269,11 @@ pub async fn run() {
.clear(ClearState::color_and_depth(0.5, 0.5, 0.5, 1.0, 1.0))
.render(&camera, skybox.into_iter().chain(&terrain), &[&light]);
}
camera.tone_mapping = ToneMapping::Aces;
camera.target_color_space = ColorSpace::Srgb;
camera.set_default_tone_and_color_mapping();
frame_input
.screen()
.apply_screen_effect(
&CopyEffect::default(),
&ScreenEffect::default(),
&camera,
&[],
Some(ColorTexture::Single(&color_texture)),
Expand Down
12 changes: 9 additions & 3 deletions src/core/render_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,12 @@ impl<'a> RenderTarget<'a> {
self.write_partially(scissor_box, || {
let mut id = (0b1u16 << 15).to_le_bytes().to_vec();
id.extend(
(0b1u16 << 13 | 0b1u16 << 12 | color_texture.id() | depth_texture.id())
.to_le_bytes(),
(0b1u16 << 13
| 0b1u16 << 12
| 0b1u16 << 10
| color_texture.id()
| depth_texture.id())
.to_le_bytes(),
);
let mut programs = self.context.programs.write().unwrap();
let program = programs.entry(id).or_insert_with(|| {
Expand Down Expand Up @@ -312,7 +316,9 @@ impl<'a> RenderTarget<'a> {
) -> &Self {
self.write_partially(scissor_box, || {
let mut id = (0b1u16 << 15).to_le_bytes().to_vec();
id.extend((0b1u16 << 13 | 0b1u16 << 11 | color_texture.id()).to_le_bytes());
id.extend(
(0b1u16 << 13 | 0b1u16 << 11 | 0b1u16 << 10 | color_texture.id()).to_le_bytes(),
);
let mut programs = self.context.programs.write().unwrap();
let program = programs.entry(id).or_insert_with(|| {
let fragment_shader_source = format!(
Expand Down
24 changes: 20 additions & 4 deletions src/renderer/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pub struct Camera {
camera: three_d_asset::Camera,
/// This tone mapping is applied to the final color of renders using this camera.
pub tone_mapping: ToneMapping,
/// The final color of renders using this camera is converted to this color space.
pub target_color_space: ColorSpace,
/// This color mapping is applied to the final color of renders using this camera.
pub color_mapping: ColorMapping,
}

impl Camera {
Expand All @@ -36,7 +36,7 @@ impl Camera {
viewport, position, target, up, height, z_near, z_far,
),
tone_mapping: ToneMapping::default(),
target_color_space: ColorSpace::default(),
color_mapping: ColorMapping::default(),
}
}

Expand All @@ -63,7 +63,7 @@ impl Camera {
z_far,
),
tone_mapping: ToneMapping::default(),
target_color_space: ColorSpace::default(),
color_mapping: ColorMapping::default(),
}
}

Expand Down Expand Up @@ -92,6 +92,22 @@ impl Camera {
10.0,
)
}

///
/// Disables the tone and color mapping so as to be ready for rendering into an intermediate render target with this camera.
///
pub fn disable_tone_and_color_mapping(&mut self) {
self.tone_mapping = ToneMapping::None;
self.color_mapping = ColorMapping::None;
}

///
/// Sets the tone and color mapping to default so as to be ready for rendering into the final render target (usually the screen) with this camera.
///
pub fn set_default_tone_and_color_mapping(&mut self) {
self.tone_mapping = ToneMapping::default();
self.color_mapping = ColorMapping::default();
}
}

use std::ops::Deref;
Expand Down
22 changes: 12 additions & 10 deletions src/renderer/camera/color_space.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
use crate::core::*;

/// Color space used for specifying the targeted color space when rendering.
///
/// Color space mapping used for mapping to/from color spaces when rendering.
///
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum ColorSpace {
/// Use this if you want to use the rendered result as input to a following render pass.
Compute = 0,
/// Use this if this is the final render pass, ie. you write to the screen or want to save it as an image.
pub enum ColorMapping {
/// No color mapping. Use this if you are rendering into an intermediate render target, ie. this is not the final render pass that renders into the screen.
None = 0,
/// Maps from compute color space (HDR or linear sRGB) to sRGB color space. Use this if this is the final render pass, ie. you write to the screen or want to save it as an image.
#[default]
Srgb = 1,
ComputeToSrgb = 1,
}

impl ColorSpace {
impl ColorMapping {
///
/// Returns the fragment shader source for mapping to the specified color space in a shader.
///
pub fn fragment_shader_source() -> &'static str {
"
uniform uint colorSpaceType;
uniform uint ColorMappingType;
vec3 color_mapping(vec3 color) {
if (colorSpaceType == 1u) {
if (ColorMappingType == 1u) {
vec3 a = vec3(0.055, 0.055, 0.055);
vec3 ap1 = vec3(1.0, 1.0, 1.0) + a;
vec3 g = vec3(2.4, 2.4, 2.4);
Expand All @@ -39,6 +41,6 @@ impl ColorSpace {
/// Sends the uniform data needed to apply this color space mapping to the fragment shader.
///
pub fn use_uniforms(&self, program: &Program) {
program.use_uniform("colorSpaceType", *self as u32);
program.use_uniform("ColorMappingType", *self as u32);
}
}
4 changes: 4 additions & 0 deletions src/renderer/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ mod copy;
#[doc(inline)]
pub use copy::*;

mod full_screen;
#[doc(inline)]
pub use full_screen::*;

mod fxaa;
#[doc(inline)]
pub use fxaa::*;
Expand Down
14 changes: 4 additions & 10 deletions src/renderer/effect/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::renderer::*;

///
/// Copies the content of the color and/or depth texture by rendering a quad with those textures applied.
/// In addition, the [ToneMapping] and target [ColorSpace] specified in the [Camera] is applied to the color.
/// The difference from [ScreenEffect] is that this effect does not apply any mapping set in the [Camera].
///
#[derive(Clone, Debug, Default)]
pub struct CopyEffect {
Expand All @@ -18,7 +18,7 @@ impl Effect for CopyEffect {
depth_texture: Option<DepthTexture>,
) -> String {
format!(
"{}{}{}{}
"{}{}
in vec2 uvs;
layout (location = 0) out vec4 outColor;
Expand All @@ -36,13 +36,9 @@ impl Effect for CopyEffect {
depth_texture
.map(|t| t.fragment_shader_source())
.unwrap_or("".to_string()),
ToneMapping::fragment_shader_source(),
ColorSpace::fragment_shader_source(),
color_texture
.map(|_| "
outColor = sample_color(uvs);
outColor.rgb = tone_mapping(outColor.rgb);
outColor.rgb = color_mapping(outColor.rgb);"
outColor = sample_color(uvs);"
.to_string())
.unwrap_or("".to_string()),
depth_texture
Expand All @@ -68,14 +64,12 @@ impl Effect for CopyEffect {
fn use_uniforms(
&self,
program: &Program,
camera: &Camera,
_camera: &Camera,
_lights: &[&dyn crate::Light],
color_texture: Option<ColorTexture>,
depth_texture: Option<DepthTexture>,
) {
if let Some(color_texture) = color_texture {
camera.tone_mapping.use_uniforms(program);
camera.target_color_space.use_uniforms(program);
color_texture.use_uniforms(program);
}
if let Some(depth_texture) = depth_texture {
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/effect/fog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Effect for FogEffect {
.expect("Must supply a depth texture to apply a fog effect")
.fragment_shader_source(),
ToneMapping::fragment_shader_source(),
ColorSpace::fragment_shader_source(),
ColorMapping::fragment_shader_source(),
include_str!("shaders/fog_effect.frag")
)
}
Expand Down Expand Up @@ -95,7 +95,7 @@ impl Effect for FogEffect {
depth_texture: Option<DepthTexture>,
) {
camera.tone_mapping.use_uniforms(program);
camera.target_color_space.use_uniforms(program);
camera.color_mapping.use_uniforms(program);
color_texture
.expect("Must supply a color texture to apply a fog effect")
.use_uniforms(program);
Expand Down
Loading

0 comments on commit ac8aedc

Please sign in to comment.