Просмотр исходного кода

scripts can output in linear colour space

master
Inderjit Gill 2 месяцев назад
Родитель
Сommit
8084e1c4a0
6 измененных файлов: 76 добавлений и 22 удалений
  1. 4
    0
      client/src/lib.rs
  2. 36
    17
      client/www/index.js
  3. 6
    4
      client/www/worker.js
  4. 1
    0
      core/src/context.rs
  5. 3
    1
      core/src/keywords.rs
  6. 26
    0
      core/src/native.rs

+ 4
- 0
client/src/lib.rs Просмотреть файл

@@ -177,6 +177,10 @@ impl Bridge {
}
}

pub fn output_linear_colour_space(&self) -> bool {
self.context.output_linear_colour_space
}

// --------------------------------------------------------------------------------

pub fn get_render_packet_geo_len(&self, packet_number: usize) -> usize {

+ 36
- 17
client/www/index.js Просмотреть файл

@@ -195,6 +195,7 @@ function setupBlitShaders(gl) {
varying vec2 vTextureCoord;

uniform sampler2D uSampler;
uniform bool uOutputLinearColourSpace;

// https:en.wikipedia.org/wiki/SRGB
vec3 linear_to_srgb(vec3 linear) {
@@ -219,7 +220,17 @@ function setupBlitShaders(gl) {
void main()
{
vec4 col = texture2D( uSampler, vTextureCoord );
gl_FragColor = vec4(linear_to_srgb(col.rgb), 1.0);

// note: you _never_ want uOutputLinearColourSpace to be set to true
// it's only here because some of the older pieces didn't correctly
// convert from linear colour space to sRGB colour space during rendering
// and this shader needs to reproduce them as intended at time of creation
//
if (uOutputLinearColourSpace) {
gl_FragColor = col;
} else {
gl_FragColor = vec4(linear_to_srgb(col.rgb), 1.0);
}
}
`;

@@ -261,6 +272,11 @@ function setupBlitShaders(gl) {
shader.mvMatrixUniform = gl.getUniformLocation(shader.program, 'uMVMatrix');
shader.textureUniform = gl.getUniformLocation(shader.program, 'uSampler');

// older versions of seni (pre 4.2.0) did not convert from sRGB space to linear before blending
// in order to retain the look of these older pieces we can't carry out the linear -> sRGB conversion
//
shader.outputLinearColourSpaceUniform = gl.getUniformLocation(shader.program, 'uOutputLinearColourSpace');

return shader;
}

@@ -498,7 +514,7 @@ class GLRenderer {

}

renderTextureToScreen(canvasWidth, canvasHeight) {
renderTextureToScreen(meta, canvasWidth, canvasHeight) {
const gl = this.gl;
const domElement = this.glDomElement;

@@ -540,6 +556,9 @@ class GLRenderer {

gl.uniform1i(shader.textureUniform, 0);

gl.uniform1i(shader.outputLinearColourSpaceUniform, meta.output_linear_colour_space);


const glVertexBuffer = this.glVertexBuffer;
const glColourBuffer = this.glColourBuffer;
const glTextureBuffer = this.glTextureBuffer;
@@ -680,7 +699,7 @@ function seniMode() {

// keywords are core to the seni language
const keywords =
makeKeywords('begin define fn if fence loop on-matrix-stack quote');
makeKeywords('begin define fn if fence loop on-matrix-stack quote meta');
const indentKeys = makeKeywords('define fence loop on-matrix-stack fn');

// functions from the common seni library
@@ -1661,7 +1680,7 @@ function updateSelectionUI(state) {
});
}

async function renderGeometryBuffers(memory, buffers, imageElement, w, h) {
async function renderGeometryBuffers(meta, memory, buffers, imageElement, w, h) {
let destWidth = undefined;
let destHeight = undefined;
if (w !== undefined && h !== undefined) {
@@ -1675,14 +1694,14 @@ async function renderGeometryBuffers(memory, buffers, imageElement, w, h) {
const stopFn = startTiming();

gGLRenderer.renderGeometryToTexture(gConfig.render_texture_width, gConfig.render_texture_height, memory, buffers);
gGLRenderer.renderTextureToScreen(destWidth, destHeight);
gGLRenderer.renderTextureToScreen(meta, destWidth, destHeight);

await gGLRenderer.copyImageDataTo(imageElement);

stopFn("rendering all buffers");
}

async function renderGeometryBuffersSection(memory, buffers, imageElement, w, h, section) {
async function renderGeometryBuffersSection(meta, memory, buffers, imageElement, w, h, section) {
let destWidth = undefined;
let destHeight = undefined;
if (w !== undefined && h !== undefined) {
@@ -1696,7 +1715,7 @@ async function renderGeometryBuffersSection(memory, buffers, imageElement, w, h,
const stopFn = startTiming();

gGLRenderer.renderGeometryToTexture(gConfig.render_texture_width, gConfig.render_texture_height, memory, buffers, section);
gGLRenderer.renderTextureToScreen(destWidth, destHeight);
gGLRenderer.renderTextureToScreen(meta, destWidth, destHeight);

await gGLRenderer.copyImageDataTo(imageElement);

@@ -1792,13 +1811,13 @@ function normalize_bitmap_url(url) {
async function renderScript(parameters, imageElement) {
const stopFn = startTiming();

let { title, memory, buffers } = await renderJob(parameters);
await renderGeometryBuffers(memory, buffers, imageElement);
let { meta, memory, buffers } = await renderJob(parameters);
await renderGeometryBuffers(meta, memory, buffers, imageElement);

if (title === '') {
if (meta.title === '') {
stopFn(`renderScript`);
} else {
stopFn(`renderScript-${title}`);
stopFn(`renderScript-${meta.title}`);
}
}

@@ -1946,14 +1965,14 @@ async function renderHighResSection(state, section) {

const stopFn = startTiming();

const { title, memory, buffers } = await renderJob({
const { meta, memory, buffers } = await renderJob({
script: state.script,
scriptHash: state.scriptHash,
genotype: undefined,
});
const [width, height] = state.highResolution;
await renderGeometryBuffersSection(memory, buffers, image, width, height, section);
stopFn(`renderHighResSection-${title}-${section}`);
await renderGeometryBuffersSection(meta, memory, buffers, image, width, height, section);
stopFn(`renderHighResSection-${meta.title}-${section}`);
image.classList.remove('hidden');
loader.classList.add('hidden');
}
@@ -2242,7 +2261,7 @@ function setupUI(controller) {

const stopFn = startTiming();

const { title, memory, buffers } = await renderJob({
const { meta, memory, buffers } = await renderJob({
script: state.script,
scriptHash: state.scriptHash,
genotype: state.genotype,
@@ -2250,9 +2269,9 @@ function setupUI(controller) {

const [width, height] = [image_resolution, image_resolution];

await renderGeometryBuffers(memory, buffers, image, width, height);
await renderGeometryBuffers(meta, memory, buffers, image, width, height);

stopFn(`renderHighRes-${title}`);
stopFn(`renderHighRes-${meta.title}`);

loader.classList.add('hidden');


+ 6
- 4
client/www/worker.js Просмотреть файл

@@ -75,9 +75,12 @@ function renderPackets({ }) {
}
}

gState.bridge.script_cleanup();
const meta = {
title: '',
output_linear_colour_space: gState.bridge.output_linear_colour_space()
};

const title = '';
gState.bridge.script_cleanup();

// make a copy of the wasm memory
//
@@ -88,11 +91,10 @@ function renderPackets({ }) {
// WTF note: Expected a perfomance cost in Chrome due to the slice operation
// but it seemed to either have no effect or to make the rendering faster!
//

const wasmMemory = gState.memory.buffer;
const memory = wasmMemory.slice();

return [{}, { title, memory, buffers }];
return [{}, { meta, memory, buffers }];
}



+ 1
- 0
core/src/context.rs Просмотреть файл

@@ -32,6 +32,7 @@ pub struct Context {
pub mappings: Mappings,
pub geometry: geometry::Geometry,
pub bitmap_cache: BitmapCache,
pub output_linear_colour_space: bool, // derive Default sets bool to false
}

impl Context {

+ 3
- 1
core/src/keywords.rs Просмотреть файл

@@ -328,6 +328,8 @@ pub enum Keyword {
InnerWidth,
#[strum(serialize = "iterations")]
Iterations,
#[strum(serialize = "linear-colour-space")]
LinearColourSpace,
#[strum(serialize = "line-width")]
LineWidth,
#[strum(serialize = "line-width-end")]
@@ -439,7 +441,7 @@ mod tests {
fn test_keyword_enums() {
assert_eq!(Keyword::False as i32, 128);
assert_eq!(Keyword::True as i32, 129);
assert_eq!(Keyword::Width as i32, 299);
assert_eq!(Keyword::Width as i32, 300);
}

#[test]

+ 26
- 0
core/src/native.rs Просмотреть файл

@@ -57,6 +57,8 @@ pub enum Native {
VectorLength,
#[strum(serialize = "probe")]
Probe,
#[strum(serialize = "meta")]
Meta,

// shapes
//
@@ -314,6 +316,7 @@ pub fn parameter_info(native: Native) -> Result<(Vec<(Keyword, Var)>, i32)> {
Native::Nth => nth_parameter_info(),
Native::VectorLength => vector_length_parameter_info(),
Native::Probe => probe_parameter_info(),
Native::Meta => meta_parameter_info(),
// shapes
Native::Line => line_parameter_info(),
Native::Rect => rect_parameter_info(),
@@ -437,6 +440,7 @@ pub fn execute_native(
Native::Nth => nth_execute(vm),
Native::VectorLength => vector_length_execute(vm),
Native::Probe => probe_execute(vm, context),
Native::Meta => meta_execute(vm, context),
// shapes
Native::Line => line_execute(vm, context),
Native::Rect => rect_execute(vm, context),
@@ -779,6 +783,28 @@ fn probe_execute(vm: &mut Vm, context: &mut Context) -> Result<Option<Var>> {
Ok(None)
}

fn meta_parameter_info() -> Result<(Vec<(Keyword, Var)>, i32)> {
Ok((
// input arguments
vec![
(Keyword::LinearColourSpace, Var::Float(0.0)),
],
// stack offset
0,
))
}

fn meta_execute(vm: &mut Vm, context: &mut Context) -> Result<Option<Var>> {
let default_mask: i32 = vm.stack_peek(2)?;

if is_arg_given(default_mask, 1) {
let scalar: f32 = vm.stack_peek(1)?;
context.output_linear_colour_space = scalar > 0.0;
}

Ok(None)
}

fn line_parameter_info() -> Result<(Vec<(Keyword, Var)>, i32)> {
Ok((
// input arguments

Загрузка…
Отмена
Сохранить