Render: integrated workspace, preview image jobs and opaque PBR (#1046)
Lands the Render workspace (R3), bounded preview-image jobs with cancellation and atomic PNG export (R4a), and opaque PBR looks as one change. - Render workspace: an overlay-free product preview on the installed GPU device. Returning to Design restores its camera. render.scene and render.settings.apply are added. - Image jobs: render.preflight/start/status/cancel/export run bounded CPU preview jobs. Export captures the job, overwrite choice and document, and checks the caller's file scope before writing. - Opaque PBR: looks can carry metal fraction, roughness and dielectric IOR. The product viewport and preview PNG use them; geometry and mass are unchanged. The v1 catalog export refuses PBR rather than dropping it. - Render setups and PBR looks are saved under design format 21. Labels are in en/de/ja/ko/zh/ru. Supersedes #706 and #800. Refs #620, #673, #756, #1004. Contributed by @0xlillith. Co-authored-by: lillith <35337584+0xlillith@users.noreply.github.com>
This commit is contained in:
1 parent
e4ef6cfe29
commit
a261aaa841
70 files changed
+5860
-101
No files matched your search
@@ -25,6 +25,7 @@ pub enum SurfaceError {
|
||||
Roughness,
|
||||
DielectricIor,
|
||||
Direction,
|
||||
Radiance,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SurfaceError {
|
||||
@@ -35,6 +36,7 @@ impl std::fmt::Display for SurfaceError {
|
||||
Self::Roughness => "perceptual roughness must be finite and in [0.045, 1]",
|
||||
Self::DielectricIor => "dielectric IOR must be finite and in [1, 3]",
|
||||
Self::Direction => "surface directions must be finite and nonzero",
|
||||
Self::Radiance => "radiance must be finite and nonnegative",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -81,15 +83,15 @@ impl OpaqueSurface {
|
||||
/// No incident radiance, cosine weight, exposure or display transfer is included.
|
||||
/// Back-facing/tangent directions return zero; malformed directions are errors.
|
||||
pub fn brdf(self, normal: Vec3, view: Vec3, light: Vec3) -> Result<Vec3, SurfaceError> {
|
||||
let n = unit(normal)?;
|
||||
let v = unit(view)?;
|
||||
let l = unit(light)?;
|
||||
let n = unit_direction(normal)?;
|
||||
let v = unit_direction(view)?;
|
||||
let l = unit_direction(light)?;
|
||||
let nv = n.dot(v).clamp(-1.0, 1.0);
|
||||
let nl = n.dot(l).clamp(-1.0, 1.0);
|
||||
if nv <= 0.0 || nl <= 0.0 {
|
||||
return Ok(Vec3::ZERO);
|
||||
}
|
||||
let h = unit(v + l)?;
|
||||
let h = unit_direction(v + l)?;
|
||||
let nh = n.dot(h).clamp(0.0, 1.0);
|
||||
let vh = v.dot(h).clamp(0.0, 1.0);
|
||||
let alpha = self.roughness * self.roughness;
|
||||
@@ -122,7 +124,8 @@ pub fn srgb8_to_linear(channel: u8) -> f64 {
|
||||
if c <= 0.04045 { c / 12.92 } else { ((c + 0.055) / 1.055).powf(2.4) }
|
||||
}
|
||||
|
||||
fn unit(v: Vec3) -> Result<Vec3, SurfaceError> {
|
||||
/// Normalize finite directions without overflow or an arbitrary magnitude threshold.
|
||||
pub fn unit_direction(v: Vec3) -> Result<Vec3, SurfaceError> {
|
||||
if !v.is_finite() {
|
||||
return Err(SurfaceError::Direction);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user