Skip to content

Instantly share code, notes, and snippets.

@wonglok
Last active February 12, 2022 03:42
Show Gist options
  • Save wonglok/39742305b184736fac94142069300d7c to your computer and use it in GitHub Desktop.
Save wonglok/39742305b184736fac94142069300d7c to your computer and use it in GitHub Desktop.
Per-Pixel-Glow-Threejs with FXAA
<AppMiniAPI>
{({ api }) => {
return (
<Starter reducedDPI={2}>
<GLMiniAPI api={api}>
{({ gpi }) => {
return (
<LinkGLToDOMAPI
init={() => {
api.now.renderMode = "pixel"; // pixel, mesh, none
}}
gpi={gpi}
api={api}
>
<SimpleBloomer gpi={gpi} api={api}></SimpleBloomer>
</LinkGLToDOMAPI>
);
}}
</GLMiniAPI>
</Starter>
);
}}
</AppMiniAPI>
// import { useEffect, useRef } from "react";
// import { Object3D } from "three";
// import { useDOMMiniEngine } from "../utils/use-mini-engine";
import { useEffect, useMemo } from "react";
import { DJCore } from "../utils/DJCore";
export const AppMiniAPI = ({
init = () => {},
children = () => {},
name = "dom-mini-api",
}) => {
const mini = useMemo(() => {
return new DJCore({
name: name,
});
}, []);
useEffect(() => {
let rAFID = 0;
let rAF = () => {
rAFID = requestAnimationFrame(rAF);
mini.work();
};
rAFID = requestAnimationFrame(rAF);
return () => {
cancelAnimationFrame(rAFID);
mini.clean();
};
}, [mini]);
useEffect(() => {
init({ api: mini });
}, [init, mini]);
// let { mini } = useDOMMiniEngine({ name, parent: parentAPI, selfloop: true });
return <>{children({ api: mini })}</>;
};
import { useEffect, useMemo, useState } from "react";
// import { useFrame, useThree } from "@react-three/fiber";
class DJCore {
constructor({ parent = false, name = "ThankyouJesusCore", global = {} }) {
let core = this;
let isAborted = false;
let isPaused = false;
this.reactTo = (key) => {
let [st, setSt] = useState(0);
useEffect(() => {
let noGo = false;
core.onChange(key, () => {
if (noGo) {
return;
}
setSt((st) => {
return st + 1;
});
});
return () => {
//
noGo = true;
};
}, []);
};
if (typeof window !== "undefined") {
global = window;
} else {
global.document = {
addEventListener: () => {},
};
global.addEventListener = () => {};
global.removeEventListener = () => {};
global.dispatchEvent = () => {};
global.performance = { now: () => {} };
global.requestAnimationFrame = () => {};
}
//
this.makeKeyReactive = this.reactTo;
this.parent = parent;
this.name = name;
this.resource = new Map();
this.get = (k) => {
return new Promise((resolve) => {
let ttt = 0;
ttt = setInterval(() => {
if (this.parent) {
if (this.resource.has(k) || this.parent.resource.has(k)) {
clearInterval(ttt);
resolve(this.resource.get(k) || this.parent.resource.get(k));
}
} else {
if (this.resource.has(k)) {
clearInterval(ttt);
resolve(this.resource.get(k));
}
}
});
});
};
let NS = `_${Math.random()}`;
this.set = (k, v) => {
this.resource.set(k, v);
global.dispatchEvent(new CustomEvent(k + NS, { detail: v }));
};
let defaultChange = { initFire: false };
this.onChange = (key, fnc, { initFire = false } = defaultChange) => {
let hh = ({ detail }) => {
fnc(detail);
};
global.addEventListener(key + NS, hh);
if (initFire === true) {
this.get(key).then((v) => {
fnc(v);
});
}
this.onClean(() => {
global.removeEventListener(key + NS, hh);
});
};
this.tasks = [];
this.resizeTasks = [];
this.cleanTasks = [];
this.onLoop = (fnc, num = 0) => {
if (num >= 0) {
this.tasks.push(fnc);
// this.tasks.sort((a, b) => {
// if (a.num > b.num) {
// return -1;
// } else if (a.num < b.num) {
// return 1;
// } else {
// return 0;
// }
// });
//
} else {
this.tasks.unshift(fnc);
}
};
this.onResize = (fnc) => {
fnc();
this.resizeTasks.push(fnc);
};
this.onClean = (func) => {
this.cleanTasks.push(func);
};
let intv = 0;
const internalResize = async () => {
for (let t of this.resizeTasks) {
await t();
}
// clearTimeout(intv);
// intv = setTimeout(async () => {
// for (let t of this.resizeTasks) {
// await t();
// }
// }, 16.8888);
};
let hresize = () => {
internalResize();
};
global.addEventListener("resize", hresize);
this.onClean(() => {
global.removeEventListener("resize", hresize);
});
this.title = "";
this.toggle = () => {
isPaused = !isPaused;
console.log(this.title, "status ::", !isPaused ? "run" : "pause");
};
this.pause = () => {
isPaused = true;
console.log(this.title, "status ::", !isPaused ? "run" : "pause");
};
this.play = () => {
isPaused = false;
console.log(this.title, "status ::", !isPaused ? "run" : "pause");
};
this.clean = () => {
console.log("clean core:", name);
isAborted = true;
isPaused = true;
try {
this.cleanTasks.forEach((e) => e());
} catch (e) {
console.error(e);
}
};
this.lastTime = global.performance.now();
this.work = () => {
this.timeNow = global.performance.now();
if (isAborted) {
return {
name: this.name,
duration: 0,
};
}
if (isPaused) {
return {
name: this.name,
duration: 0,
};
}
const start = global.performance.now();
try {
let t = this.timeNow;
const lt = this.lastTime;
let dt = t - lt;
this.lastTime = t;
dt = dt / 1000;
t = t / 1000;
//
if (dt >= 0.1) {
dt = 0.1;
}
this.tasks.forEach((e) => e(dt, dt));
} catch (e) {
console.error(e);
}
const end = global.performance.now();
const duration = end - start;
return {
name: this.name,
duration,
};
};
this.ready = new Proxy(
{},
{
get: (obj, key) => {
return this.get(key);
},
}
);
this.now = new Proxy(
{},
{
get: (obj, key) => {
if (this.parent) {
return this.resource.get(key) || this.parent.resource.get(key);
} else {
return this.resource.get(key);
}
},
set: (o, key, value) => {
this.set(key, value);
return true;
},
}
);
if (parent) {
parent.onLoop(() => {
this.work();
});
parent.onClean(() => {
this.clean();
});
}
// console.log(
// "make core:",
// JSON.stringify({
// name: this.name,
// parent: this.parent.name,
// })
// );
this.autoEvent = (eventName, fnc, dom = global, config) => {
//
dom.addEventListener(eventName, fnc, config);
this.onClean(() => {
dom.removeEventListener(eventName, fnc);
});
};
let self = this;
this.makeNode = ({ name = "node" }) => {
// subname
let subname = name;
let parentName = self.name;
return new DJCore({
parent: self,
name: `${parentName}-${subname}`,
});
};
this.scope = (fnc) => {
let sub = useMemo(() => {
let sub = new DJCore({
parent: self,
name: "sub-node",
});
return sub;
}, []);
useEffect(() => {
fnc({ sub });
return () => {
sub.clean();
};
}, [sub]);
return { sub };
};
this.name = (name) => (v) => {
this.now[name] = v;
};
// this.syncGL = () => {
// useFrame((prop) => {
// for (let kn in prop) {
// this.resource.set(kn, prop[kn]);
// }
// });
// };
//
}
}
export { DJCore };
//
// FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com)
//----------------------------------------------------------------------------------
// File: es3-kepler\FXAA\assets\shaders/FXAA_DefaultES.frag
// SDK Version: v3.00
// Email: gameworks@nvidia.com
// Site: http://developer.nvidia.com/
//
// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS\'\' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//----------------------------------------------------------------------------------
export const FXAAFrag = `
precision highp float;
// uniform sampler2D tDiffuse;
uniform vec2 resolution;
// varying vec2 vUv;
#define FXAA_PC 1
#define FXAA_GLSL_100 1
#define FXAA_QUALITY_PRESET 12
#define FXAA_GREEN_AS_LUMA 1
/*--------------------------------------------------------------------------*/
#ifndef FXAA_PC_CONSOLE
//
// The console algorithm for PC is included
// for developers targeting really low spec machines.
// Likely better to just run FXAA_PC, and use a really low preset.
//
#define FXAA_PC_CONSOLE 0
#endif
/*--------------------------------------------------------------------------*/
#ifndef FXAA_GLSL_120
#define FXAA_GLSL_120 0
#endif
/*--------------------------------------------------------------------------*/
#ifndef FXAA_GLSL_130
#define FXAA_GLSL_130 0
#endif
/*--------------------------------------------------------------------------*/
#ifndef FXAA_HLSL_3
#define FXAA_HLSL_3 0
#endif
/*--------------------------------------------------------------------------*/
#ifndef FXAA_HLSL_4
#define FXAA_HLSL_4 0
#endif
/*--------------------------------------------------------------------------*/
#ifndef FXAA_HLSL_5
#define FXAA_HLSL_5 0
#endif
/*==========================================================================*/
#ifndef FXAA_GREEN_AS_LUMA
//
// For those using non-linear color,
// and either not able to get luma in alpha, or not wanting to,
// this enables FXAA to run using green as a proxy for luma.
// So with this enabled, no need to pack luma in alpha.
//
// This will turn off AA on anything which lacks some amount of green.
// Pure red and blue or combination of only R and B, will get no AA.
//
// Might want to lower the settings for both,
// fxaaConsoleEdgeThresholdMin
// fxaaQualityEdgeThresholdMin
// In order to insure AA does not get turned off on colors
// which contain a minor amount of green.
//
// 1 = On.
// 0 = Off.
//
#define FXAA_GREEN_AS_LUMA 0
#endif
/*--------------------------------------------------------------------------*/
#ifndef FXAA_EARLY_EXIT
//
// Controls algorithm\'s early exit path.
// On PS3 turning this ON adds 2 cycles to the shader.
// On 360 turning this OFF adds 10ths of a millisecond to the shader.
// Turning this off on console will result in a more blurry image.
// So this defaults to on.
//
// 1 = On.
// 0 = Off.
//
#define FXAA_EARLY_EXIT 1
#endif
/*--------------------------------------------------------------------------*/
#ifndef FXAA_DISCARD
//
// Only valid for PC OpenGL currently.
// Probably will not work when FXAA_GREEN_AS_LUMA = 1.
//
// 1 = Use discard on pixels which don\'t need AA.
// For APIs which enable concurrent TEX+ROP from same surface.
// 0 = Return unchanged color on pixels which don\'t need AA.
//
#define FXAA_DISCARD 0
#endif
/*--------------------------------------------------------------------------*/
#ifndef FXAA_FAST_PIXEL_OFFSET
//
// Used for GLSL 120 only.
//
// 1 = GL API supports fast pixel offsets
// 0 = do not use fast pixel offsets
//
#ifdef GL_EXT_gpu_shader4
#define FXAA_FAST_PIXEL_OFFSET 1
#endif
#ifdef GL_NV_gpu_shader5
#define FXAA_FAST_PIXEL_OFFSET 1
#endif
#ifdef GL_ARB_gpu_shader5
#define FXAA_FAST_PIXEL_OFFSET 1
#endif
#ifndef FXAA_FAST_PIXEL_OFFSET
#define FXAA_FAST_PIXEL_OFFSET 0
#endif
#endif
/*--------------------------------------------------------------------------*/
#ifndef FXAA_GATHER4_ALPHA
//
// 1 = API supports gather4 on alpha channel.
// 0 = API does not support gather4 on alpha channel.
//
#if (FXAA_HLSL_5 == 1)
#define FXAA_GATHER4_ALPHA 1
#endif
#ifdef GL_ARB_gpu_shader5
#define FXAA_GATHER4_ALPHA 1
#endif
#ifdef GL_NV_gpu_shader5
#define FXAA_GATHER4_ALPHA 1
#endif
#ifndef FXAA_GATHER4_ALPHA
#define FXAA_GATHER4_ALPHA 0
#endif
#endif
/*============================================================================
FXAA QUALITY - TUNING KNOBS
------------------------------------------------------------------------------
NOTE the other tuning knobs are now in the shader function inputs!
============================================================================*/
#ifndef FXAA_QUALITY_PRESET
//
// Choose the quality preset.
// This needs to be compiled into the shader as it effects code.
// Best option to include multiple presets is to
// in each shader define the preset, then include this file.
//
// OPTIONS
// -----------------------------------------------------------------------
// 10 to 15 - default medium dither (10=fastest, 15=highest quality)
// 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
// 39 - no dither, very expensive
//
// NOTES
// -----------------------------------------------------------------------
// 12 = slightly faster then FXAA 3.9 and higher edge quality (default)
// 13 = about same speed as FXAA 3.9 and better than 12
// 23 = closest to FXAA 3.9 visually and performance wise
// _ = the lowest digit is directly related to performance
// _ = the highest digit is directly related to style
//
#define FXAA_QUALITY_PRESET 12
#endif
/*============================================================================
FXAA QUALITY - PRESETS
============================================================================*/
/*============================================================================
FXAA QUALITY - MEDIUM DITHER PRESETS
============================================================================*/
#if (FXAA_QUALITY_PRESET == 10)
#define FXAA_QUALITY_PS 3
#define FXAA_QUALITY_P0 1.5
#define FXAA_QUALITY_P1 3.0
#define FXAA_QUALITY_P2 12.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 11)
#define FXAA_QUALITY_PS 4
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 3.0
#define FXAA_QUALITY_P3 12.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 12)
#define FXAA_QUALITY_PS 5
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 4.0
#define FXAA_QUALITY_P4 12.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 13)
#define FXAA_QUALITY_PS 6
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 4.0
#define FXAA_QUALITY_P5 12.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 14)
#define FXAA_QUALITY_PS 7
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 2.0
#define FXAA_QUALITY_P5 4.0
#define FXAA_QUALITY_P6 12.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 15)
#define FXAA_QUALITY_PS 8
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 2.0
#define FXAA_QUALITY_P5 2.0
#define FXAA_QUALITY_P6 4.0
#define FXAA_QUALITY_P7 12.0
#endif
/*============================================================================
FXAA QUALITY - LOW DITHER PRESETS
============================================================================*/
#if (FXAA_QUALITY_PRESET == 20)
#define FXAA_QUALITY_PS 3
#define FXAA_QUALITY_P0 1.5
#define FXAA_QUALITY_P1 2.0
#define FXAA_QUALITY_P2 8.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 21)
#define FXAA_QUALITY_PS 4
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 8.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 22)
#define FXAA_QUALITY_PS 5
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 8.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 23)
#define FXAA_QUALITY_PS 6
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 2.0
#define FXAA_QUALITY_P5 8.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 24)
#define FXAA_QUALITY_PS 7
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 2.0
#define FXAA_QUALITY_P5 3.0
#define FXAA_QUALITY_P6 8.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 25)
#define FXAA_QUALITY_PS 8
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 2.0
#define FXAA_QUALITY_P5 2.0
#define FXAA_QUALITY_P6 4.0
#define FXAA_QUALITY_P7 8.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 26)
#define FXAA_QUALITY_PS 9
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 2.0
#define FXAA_QUALITY_P5 2.0
#define FXAA_QUALITY_P6 2.0
#define FXAA_QUALITY_P7 4.0
#define FXAA_QUALITY_P8 8.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 27)
#define FXAA_QUALITY_PS 10
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 2.0
#define FXAA_QUALITY_P5 2.0
#define FXAA_QUALITY_P6 2.0
#define FXAA_QUALITY_P7 2.0
#define FXAA_QUALITY_P8 4.0
#define FXAA_QUALITY_P9 8.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 28)
#define FXAA_QUALITY_PS 11
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 2.0
#define FXAA_QUALITY_P5 2.0
#define FXAA_QUALITY_P6 2.0
#define FXAA_QUALITY_P7 2.0
#define FXAA_QUALITY_P8 2.0
#define FXAA_QUALITY_P9 4.0
#define FXAA_QUALITY_P10 8.0
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PRESET == 29)
#define FXAA_QUALITY_PS 12
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.5
#define FXAA_QUALITY_P2 2.0
#define FXAA_QUALITY_P3 2.0
#define FXAA_QUALITY_P4 2.0
#define FXAA_QUALITY_P5 2.0
#define FXAA_QUALITY_P6 2.0
#define FXAA_QUALITY_P7 2.0
#define FXAA_QUALITY_P8 2.0
#define FXAA_QUALITY_P9 2.0
#define FXAA_QUALITY_P10 4.0
#define FXAA_QUALITY_P11 8.0
#endif
/*============================================================================
FXAA QUALITY - EXTREME QUALITY
============================================================================*/
#if (FXAA_QUALITY_PRESET == 39)
#define FXAA_QUALITY_PS 12
#define FXAA_QUALITY_P0 1.0
#define FXAA_QUALITY_P1 1.0
#define FXAA_QUALITY_P2 1.0
#define FXAA_QUALITY_P3 1.0
#define FXAA_QUALITY_P4 1.0
#define FXAA_QUALITY_P5 1.5
#define FXAA_QUALITY_P6 2.0
#define FXAA_QUALITY_P7 2.0
#define FXAA_QUALITY_P8 2.0
#define FXAA_QUALITY_P9 2.0
#define FXAA_QUALITY_P10 4.0
#define FXAA_QUALITY_P11 8.0
#endif
/*============================================================================
API PORTING
============================================================================*/
#if (FXAA_GLSL_100 == 1) || (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1)
#define FxaaBool bool
#define FxaaDiscard discard
#define FxaaFloat float
#define FxaaFloat2 vec2
#define FxaaFloat3 vec3
#define FxaaFloat4 vec4
#define FxaaHalf float
#define FxaaHalf2 vec2
#define FxaaHalf3 vec3
#define FxaaHalf4 vec4
#define FxaaInt2 ivec2
#define FxaaSat(x) clamp(x, 0.0, 1.0)
#define FxaaTex sampler2D
#else
#define FxaaBool bool
#define FxaaDiscard clip(-1)
#define FxaaFloat float
#define FxaaFloat2 float2
#define FxaaFloat3 float3
#define FxaaFloat4 float4
#define FxaaHalf half
#define FxaaHalf2 half2
#define FxaaHalf3 half3
#define FxaaHalf4 half4
#define FxaaSat(x) saturate(x)
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_GLSL_100 == 1)
#define FxaaTexTop(t, p) texture2D(t, p, 0.0)
#define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), 0.0)
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_GLSL_120 == 1)
// Requires,
// #version 120
// And at least,
// #extension GL_EXT_gpu_shader4 : enable
// (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)
#define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)
#if (FXAA_FAST_PIXEL_OFFSET == 1)
#define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)
#else
#define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)
#endif
#if (FXAA_GATHER4_ALPHA == 1)
// use #extension GL_ARB_gpu_shader5 : enable
#define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
#define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
#define FxaaTexGreen4(t, p) textureGather(t, p, 1)
#define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
#endif
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_GLSL_130 == 1)
// Requires "#version 130" or better
#define FxaaTexTop(t, p) textureLod(t, p, 0.0)
#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
#if (FXAA_GATHER4_ALPHA == 1)
// use #extension GL_ARB_gpu_shader5 : enable
#define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
#define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
#define FxaaTexGreen4(t, p) textureGather(t, p, 1)
#define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
#endif
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_HLSL_3 == 1)
#define FxaaInt2 float2
#define FxaaTex sampler2D
#define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))
#define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_HLSL_4 == 1)
#define FxaaInt2 int2
struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
#define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_HLSL_5 == 1)
#define FxaaInt2 int2
struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
#define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
#define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p)
#define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o)
#define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p)
#define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o)
#endif
/*============================================================================
GREEN AS LUMA OPTION SUPPORT FUNCTION
============================================================================*/
#if (FXAA_GREEN_AS_LUMA == 0)
FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }
#else
FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }
#endif
/*============================================================================
FXAA3 QUALITY - PC
============================================================================*/
#if (FXAA_PC == 1)
/*--------------------------------------------------------------------------*/
FxaaFloat4 FxaaPixelShader(
//
// Use noperspective interpolation here (turn off perspective interpolation).
// {xy} = center of pixel
FxaaFloat2 pos,
//
// Used only for FXAA Console, and not used on the 360 version.
// Use noperspective interpolation here (turn off perspective interpolation).
// {xy_} = upper left of pixel
// {_zw} = lower right of pixel
FxaaFloat4 fxaaConsolePosPos,
//
// Input color texture.
// {rgb_} = color in linear or perceptual color space
// if (FXAA_GREEN_AS_LUMA == 0)
// {__a} = luma in perceptual color space (not linear)
FxaaTex tex,
//
// Only used on the optimized 360 version of FXAA Console.
// For everything but 360, just use the same input here as for "tex".
// For 360, same texture, just alias with a 2nd sampler.
// This sampler needs to have an exponent bias of -1.
FxaaTex fxaaConsole360TexExpBiasNegOne,
//
// Only used on the optimized 360 version of FXAA Console.
// For everything but 360, just use the same input here as for "tex".
// For 360, same texture, just alias with a 3nd sampler.
// This sampler needs to have an exponent bias of -2.
FxaaTex fxaaConsole360TexExpBiasNegTwo,
//
// Only used on FXAA Quality.
// This must be from a constant/uniform.
// {x_} = 1.0/screenWidthInPixels
// {_y} = 1.0/screenHeightInPixels
FxaaFloat2 fxaaQualityRcpFrame,
//
// Only used on FXAA Console.
// This must be from a constant/uniform.
// This effects sub-pixel AA quality and inversely sharpness.
// Where N ranges between,
// N = 0.50 (default)
// N = 0.33 (sharper)
// {x__} = -N/screenWidthInPixels
// {_y_} = -N/screenHeightInPixels
// {_z_} = N/screenWidthInPixels
// {__w} = N/screenHeightInPixels
FxaaFloat4 fxaaConsoleRcpFrameOpt,
//
// Only used on FXAA Console.
// Not used on 360, but used on PS3 and PC.
// This must be from a constant/uniform.
// {x__} = -2.0/screenWidthInPixels
// {_y_} = -2.0/screenHeightInPixels
// {_z_} = 2.0/screenWidthInPixels
// {__w} = 2.0/screenHeightInPixels
FxaaFloat4 fxaaConsoleRcpFrameOpt2,
//
// Only used on FXAA Console.
// Only used on 360 in place of fxaaConsoleRcpFrameOpt2.
// This must be from a constant/uniform.
// {x__} = 8.0/screenWidthInPixels
// {_y_} = 8.0/screenHeightInPixels
// {_z_} = -4.0/screenWidthInPixels
// {__w} = -4.0/screenHeightInPixels
FxaaFloat4 fxaaConsole360RcpFrameOpt2,
//
// Only used on FXAA Quality.
// This used to be the FXAA_QUALITY_SUBPIX define.
// It is here now to allow easier tuning.
// Choose the amount of sub-pixel aliasing removal.
// This can effect sharpness.
// 1.00 - upper limit (softer)
// 0.75 - default amount of filtering
// 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
// 0.25 - almost off
// 0.00 - completely off
FxaaFloat fxaaQualitySubpix,
//
// Only used on FXAA Quality.
// This used to be the FXAA_QUALITY_EDGE_THRESHOLD define.
// It is here now to allow easier tuning.
// The minimum amount of local contrast required to apply algorithm.
// 0.333 - too little (faster)
// 0.250 - low quality
// 0.166 - default
// 0.125 - high quality
// 0.063 - overkill (slower)
FxaaFloat fxaaQualityEdgeThreshold,
//
// Only used on FXAA Quality.
// This used to be the FXAA_QUALITY_EDGE_THRESHOLD_MIN define.
// It is here now to allow easier tuning.
// Trims the algorithm from processing darks.
// 0.0833 - upper limit (default, the start of visible unfiltered edges)
// 0.0625 - high quality (faster)
// 0.0312 - visible limit (slower)
// Special notes when using FXAA_GREEN_AS_LUMA,
// Likely want to set this to zero.
// As colors that are mostly not-green
// will appear very dark in the green channel!
// Tune by looking at mostly non-green content,
// then start at zero and increase until aliasing is a problem.
FxaaFloat fxaaQualityEdgeThresholdMin,
//
// Only used on FXAA Console.
// This used to be the FXAA_CONSOLE_EDGE_SHARPNESS define.
// It is here now to allow easier tuning.
// This does not effect PS3, as this needs to be compiled in.
// Use FXAA_CONSOLE_PS3_EDGE_SHARPNESS for PS3.
// Due to the PS3 being ALU bound,
// there are only three safe values here: 2 and 4 and 8.
// These options use the shaders ability to a free *|/ by 2|4|8.
// For all other platforms can be a non-power of two.
// 8.0 is sharper (default!!!)
// 4.0 is softer
// 2.0 is really soft (good only for vector graphics inputs)
FxaaFloat fxaaConsoleEdgeSharpness,
//
// Only used on FXAA Console.
// This used to be the FXAA_CONSOLE_EDGE_THRESHOLD define.
// It is here now to allow easier tuning.
// This does not effect PS3, as this needs to be compiled in.
// Use FXAA_CONSOLE_PS3_EDGE_THRESHOLD for PS3.
// Due to the PS3 being ALU bound,
// there are only two safe values here: 1/4 and 1/8.
// These options use the shaders ability to a free *|/ by 2|4|8.
// The console setting has a different mapping than the quality setting.
// Other platforms can use other values.
// 0.125 leaves less aliasing, but is softer (default!!!)
// 0.25 leaves more aliasing, and is sharper
FxaaFloat fxaaConsoleEdgeThreshold,
//
// Only used on FXAA Console.
// This used to be the FXAA_CONSOLE_EDGE_THRESHOLD_MIN define.
// It is here now to allow easier tuning.
// Trims the algorithm from processing darks.
// The console setting has a different mapping than the quality setting.
// This only applies when FXAA_EARLY_EXIT is 1.
// This does not apply to PS3,
// PS3 was simplified to avoid more shader instructions.
// 0.06 - faster but more aliasing in darks
// 0.05 - default
// 0.04 - slower and less aliasing in darks
// Special notes when using FXAA_GREEN_AS_LUMA,
// Likely want to set this to zero.
// As colors that are mostly not-green
// will appear very dark in the green channel!
// Tune by looking at mostly non-green content,
// then start at zero and increase until aliasing is a problem.
FxaaFloat fxaaConsoleEdgeThresholdMin,
//
// Extra constants for 360 FXAA Console only.
// Use zeros or anything else for other platforms.
// These must be in physical constant registers and NOT immediates.
// Immediates will result in compiler un-optimizing.
// {xyzw} = float4(1.0, -1.0, 0.25, -0.25)
FxaaFloat4 fxaaConsole360ConstDir
) {
/*--------------------------------------------------------------------------*/
FxaaFloat2 posM;
posM.x = pos.x;
posM.y = pos.y;
#if (FXAA_GATHER4_ALPHA == 1)
#if (FXAA_DISCARD == 0)
FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
#if (FXAA_GREEN_AS_LUMA == 0)
#define lumaM rgbyM.w
#else
#define lumaM rgbyM.y
#endif
#endif
#if (FXAA_GREEN_AS_LUMA == 0)
FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);
FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));
#else
FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);
FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));
#endif
#if (FXAA_DISCARD == 1)
#define lumaM luma4A.w
#endif
#define lumaE luma4A.z
#define lumaS luma4A.x
#define lumaSE luma4A.y
#define lumaNW luma4B.w
#define lumaN luma4B.z
#define lumaW luma4B.x
#else
FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
#if (FXAA_GREEN_AS_LUMA == 0)
#define lumaM rgbyM.w
#else
#define lumaM rgbyM.y
#endif
#if (FXAA_GLSL_100 == 1)
FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 0.0, 1.0), fxaaQualityRcpFrame.xy));
FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 1.0, 0.0), fxaaQualityRcpFrame.xy));
FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 0.0,-1.0), fxaaQualityRcpFrame.xy));
FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2(-1.0, 0.0), fxaaQualityRcpFrame.xy));
#else
FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));
FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));
#endif
#endif
/*--------------------------------------------------------------------------*/
FxaaFloat maxSM = max(lumaS, lumaM);
FxaaFloat minSM = min(lumaS, lumaM);
FxaaFloat maxESM = max(lumaE, maxSM);
FxaaFloat minESM = min(lumaE, minSM);
FxaaFloat maxWN = max(lumaN, lumaW);
FxaaFloat minWN = min(lumaN, lumaW);
FxaaFloat rangeMax = max(maxWN, maxESM);
FxaaFloat rangeMin = min(minWN, minESM);
FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
FxaaFloat range = rangeMax - rangeMin;
FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
FxaaBool earlyExit = range < rangeMaxClamped;
/*--------------------------------------------------------------------------*/
if(earlyExit)
#if (FXAA_DISCARD == 1)
FxaaDiscard;
#else
return rgbyM;
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_GATHER4_ALPHA == 0)
#if (FXAA_GLSL_100 == 1)
FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2(-1.0,-1.0), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 1.0, 1.0), fxaaQualityRcpFrame.xy));
FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 1.0,-1.0), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2(-1.0, 1.0), fxaaQualityRcpFrame.xy));
#else
FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
#endif
#else
FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
#endif
/*--------------------------------------------------------------------------*/
FxaaFloat lumaNS = lumaN + lumaS;
FxaaFloat lumaWE = lumaW + lumaE;
FxaaFloat subpixRcpRange = 1.0/range;
FxaaFloat subpixNSWE = lumaNS + lumaWE;
FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;
FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;
/*--------------------------------------------------------------------------*/
FxaaFloat lumaNESE = lumaNE + lumaSE;
FxaaFloat lumaNWNE = lumaNW + lumaNE;
FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
/*--------------------------------------------------------------------------*/
FxaaFloat lumaNWSW = lumaNW + lumaSW;
FxaaFloat lumaSWSE = lumaSW + lumaSE;
FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;
FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;
/*--------------------------------------------------------------------------*/
FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;
FxaaFloat lengthSign = fxaaQualityRcpFrame.x;
FxaaBool horzSpan = edgeHorz >= edgeVert;
FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
/*--------------------------------------------------------------------------*/
if(!horzSpan) lumaN = lumaW;
if(!horzSpan) lumaS = lumaE;
if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;
/*--------------------------------------------------------------------------*/
FxaaFloat gradientN = lumaN - lumaM;
FxaaFloat gradientS = lumaS - lumaM;
FxaaFloat lumaNN = lumaN + lumaM;
FxaaFloat lumaSS = lumaS + lumaM;
FxaaBool pairN = abs(gradientN) >= abs(gradientS);
FxaaFloat gradient = max(abs(gradientN), abs(gradientS));
if(pairN) lengthSign = -lengthSign;
FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
/*--------------------------------------------------------------------------*/
FxaaFloat2 posB;
posB.x = posM.x;
posB.y = posM.y;
FxaaFloat2 offNP;
offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
if(!horzSpan) posB.x += lengthSign * 0.5;
if( horzSpan) posB.y += lengthSign * 0.5;
/*--------------------------------------------------------------------------*/
FxaaFloat2 posN;
posN.x = posB.x - offNP.x * FXAA_QUALITY_P0;
posN.y = posB.y - offNP.y * FXAA_QUALITY_P0;
FxaaFloat2 posP;
posP.x = posB.x + offNP.x * FXAA_QUALITY_P0;
posP.y = posB.y + offNP.y * FXAA_QUALITY_P0;
FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;
FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
FxaaFloat subpixE = subpixC * subpixC;
FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
/*--------------------------------------------------------------------------*/
if(!pairN) lumaNN = lumaSS;
FxaaFloat gradientScaled = gradient * 1.0/4.0;
FxaaFloat lumaMM = lumaM - lumaNN * 0.5;
FxaaFloat subpixF = subpixD * subpixE;
FxaaBool lumaMLTZero = lumaMM < 0.0;
/*--------------------------------------------------------------------------*/
lumaEndN -= lumaNN * 0.5;
lumaEndP -= lumaNN * 0.5;
FxaaBool doneN = abs(lumaEndN) >= gradientScaled;
FxaaBool doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P1;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P1;
FxaaBool doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P1;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P1;
/*--------------------------------------------------------------------------*/
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P2;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P2;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P2;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P2;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 3)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P3;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P3;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P3;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P3;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 4)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P4;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P4;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P4;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P4;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 5)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P5;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P5;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P5;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P5;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 6)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P6;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P6;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P6;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P6;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 7)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P7;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P7;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P7;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P7;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 8)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P8;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P8;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P8;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P8;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 9)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P9;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P9;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P9;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P9;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 10)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P10;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P10;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P10;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P10;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 11)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P11;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P11;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P11;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P11;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY_PS > 12)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P12;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P12;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P12;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P12;
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
/*--------------------------------------------------------------------------*/
FxaaFloat dstN = posM.x - posN.x;
FxaaFloat dstP = posP.x - posM.x;
if(!horzSpan) dstN = posM.y - posN.y;
if(!horzSpan) dstP = posP.y - posM.y;
/*--------------------------------------------------------------------------*/
FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
FxaaFloat spanLength = (dstP + dstN);
FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
FxaaFloat spanLengthRcp = 1.0/spanLength;
/*--------------------------------------------------------------------------*/
FxaaBool directionN = dstN < dstP;
FxaaFloat dst = min(dstN, dstP);
FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;
FxaaFloat subpixG = subpixF * subpixF;
FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
FxaaFloat subpixH = subpixG * fxaaQualitySubpix;
/*--------------------------------------------------------------------------*/
FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
#if (FXAA_DISCARD == 1)
return FxaaTexTop(tex, posM);
#else
return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);
#endif
}
/*==========================================================================*/
#endif
`;
// import { useEffect, useRef } from "react";
// import { Object3D } from "three";
import { useFrame, useThree } from "@react-three/fiber";
import { useEffect, useMemo } from "react";
import { DJCore } from "../utils/DJCore";
export const GLMiniAPI = ({
children = () => {},
name = "gl-mini-api",
api,
}) => {
let { get } = useThree();
const mini = useMemo(() => {
let gpi = new DJCore({
name: name,
parent: api,
});
api.now.gpi = gpi;
let st = get();
for (const kn in st) {
gpi.resource.set(kn, st[kn]);
}
return gpi;
}, []);
useEffect(() => {
return () => {
mini.clean();
};
}, [mini]);
useFrame(() => {}, 100);
return <group>{children({ gpi: mini })}</group>;
};
export const LinkGLToDOMAPI = ({ init = () => {}, gpi, api, children }) => {
api.reactTo("gpi");
useEffect(() => {
init();
}, []);
//
return api.now.gpi ? children : null;
};
//
import { useEffect, useRef } from "react";
import { useFrame } from "@react-three/fiber";
import {
Color,
DoubleSide,
Layers,
LinearEncoding,
MeshBasicMaterial,
MeshLambertMaterial,
MeshMatcapMaterial,
MeshPhongMaterial,
MeshPhysicalMaterial,
MeshStandardMaterial,
MeshToonMaterial,
ShaderMaterial,
sRGBEncoding,
Vector2,
WebGLRenderTarget,
} from "three";
import { FullScreenQuad } from "three/examples/jsm/postprocessing/Pass";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass";
import { FXAAFrag } from "./FXAAFrag";
export const ENTIRE_SCENE = 0;
export const BLOOM_SCENE = 1;
export const DARK_SCENE = 2;
export const enableBloom = (item) => {
item.layers.enable(BLOOM_SCENE);
};
export const enableDarken = (item) => {
item.layers.enable(DARK_SCENE);
};
export class BloomLayer {
constructor({ mini, api }) {
let { get } = mini.now;
let resBase = new Vector2();
resBase.copy({
x: get().gl.domElement.clientWidth,
y: get().gl.domElement.clientHeight,
});
resBase.multiplyScalar(0.4);
get().gl.outputEncoding = sRGBEncoding;
let efComposer = new EffectComposer(get().gl);
let renderPass = new RenderPass(get().scene, get().camera);
mini.onResize(() => {
resBase.copy({
x: get().gl.domElement.clientWidth,
y: get().gl.domElement.clientHeight,
});
resBase.multiplyScalar(0.4);
renderPass.setSize(resBase.x, resBase.y);
});
efComposer.addPass(renderPass);
// let unrealPass = new UnrealBloomPass(resBase, 1.0, 0.8, 0.2);
let unrealPass = new UnrealBloomPass(resBase, 3.0, 1, 0.05);
window.unrealPass = unrealPass;
mini.onResize(() => {
resBase.copy({
x: get().gl.domElement.clientWidth,
y: get().gl.domElement.clientHeight,
});
resBase.multiplyScalar(0.4);
unrealPass.setSize(resBase.x, resBase.y);
});
efComposer.addPass(unrealPass);
efComposer.renderToScreen = false;
let dark = new Color("#000000");
// let darkMat = new MeshBasicMaterial({ color: 0x000000, skinning: true })
let baseLayer = new Layers();
baseLayer.disableAll();
baseLayer.enable(ENTIRE_SCENE);
//
let bloomLayer = new Layers();
bloomLayer.disableAll();
bloomLayer.enable(BLOOM_SCENE);
//
let darkLayer = new Layers();
darkLayer.disableAll();
darkLayer.enable(DARK_SCENE);
// let uniqueMaterialMap = new Map();
// let full = onBeforeCompileForStdMat.toString();
let getSig = (uuid) => {
return "done" + uuid;
};
let setup = () => {
let { scene } = get();
// let darken = new MeshBasicMaterial({
// color: 0x000000,
// transparent: false,
// opacity: 0,
// envMap: null,
// side: DoubleSide,
// });
scene.traverse((it) => {
if (
// (it.materual && it.material.needsUpdate) ||
it.material &&
it.userData.____lastSig !== getSig(it.uuid) &&
(it.material instanceof MeshStandardMaterial ||
it.material instanceof MeshPhongMaterial ||
it.material instanceof MeshBasicMaterial ||
it.material instanceof MeshLambertMaterial ||
it.material instanceof MeshMatcapMaterial ||
it.material instanceof MeshPhysicalMaterial ||
it.material instanceof MeshToonMaterial)
) {
// let loc = window.location.href;
// it[loc] = it[loc] || {};
let hh = (shader) => {
let globalDarkening = { value: 1 };
let bloomAPI = {
shine: () => {
globalDarkening.value = 0;
},
dim: () => {
globalDarkening.value = 1;
},
restore: () => {
globalDarkening.value = 2;
},
suspense: () => {
globalDarkening.value = 3;
},
pixelScan: () => {
globalDarkening.value = 4;
},
meshGlow: () => {
globalDarkening.value = 5;
},
};
shader.uniforms.globalDarkening = globalDarkening;
let atBegin = `
uniform float globalDarkening;
`;
let atEnd = `
if (globalDarkening == 4.0) {
float aE = (totalEmissiveRadiance.r + totalEmissiveRadiance.g + totalEmissiveRadiance.b) / 3.0;
if (aE >= 0.0) {
gl_FragColor.rgb = gl_FragColor.rgb * aE;
} else {
// darken
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
} else if (globalDarkening == 1.0) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
`;
shader.fragmentShader = `${atBegin.trim()}\n${
shader.fragmentShader
}`;
shader.fragmentShader = shader.fragmentShader.replace(
`#include <dithering_fragment>`,
`#include <dithering_fragment>\n${atEnd.trim()}`
);
it.userData.bloomAPI = bloomAPI;
};
// let orig = it.material;
// let bloomAPI = {
// shine: () => {
// it.material = orig;
// globalDarkening.value = false;
// },
// dim: () => {
// it.material = darken;
// globalDarkening.value = true;
// },
// };
// it.userData.bloomAPIBackup = bloomAPI;
it.userData.____lastSig = getSig(it.uuid);
it.material.onBeforeCompile = hh;
it.material.customProgramCacheKey = () => {
return getSig(it.uuid);
};
it.material.needsUpdate = true;
}
});
};
// BloomLayer.darkenMap = BloomLayer.darkenMap || ;
// let enableDarkenMap = new Map();
let setBloomSceneMat = () => {
let { scene } = get();
//
scene.traverse((it) => {
// if (it.material && it.material.emissive) {
// if (it.material.emissive) {
// let sum =
// it.material.emissive.r +
// it.material.emissive.g +
// it.material.emissive.b;
// let avg = sum / 3;
// let inten = it?.material?.emissiveIntensity || 0;
// let score = avg * inten;
// if (score > 0) {
// it.userData.enableBloom = true;
// }
// }
// }
// if (
// it?.userData?.enableBloom ||
// it?.material?.userData?.enableBloom ||
// it?.userData?.forceBloom ||
// it?.material?.userData?.forceBloom
// ) {
// if (it?.userData?.bloomAPI?.shine) {
// it.userData.bloomAPI.shine();
// }
// } else {
// if (it?.userData?.bloomAPI?.dim) {
// it.userData.bloomAPI.dim();
// }
// }
// if (
// it?.userData?.enableBloom ||
// it?.material?.userData?.enableBloom ||
// it?.userData?.forceBloom ||
// it?.material?.userData?.forceBloom
// ) {
// if (it.material?.emissive) {
// it.material.emissive.r = 0.01;
// it.material.emissive.g = 0.01;
// it.material.emissive.b = 0.01;
// it.material.emissiveIntensity = 1.0;
// }
// }
if (api.now.renderMode === "pixel") {
if (it?.userData?.bloomAPI?.pixelScan) {
it.userData.bloomAPI.pixelScan();
}
} else if (api.now.renderMode === "mesh") {
if (
it?.userData?.enableBloom ||
it?.material?.userData?.enableBloom ||
it?.userData?.forceBloom ||
it?.material?.userData?.forceBloom
) {
if (it.userData?.bloomAPI?.shine) {
it.userData.bloomAPI.shine();
}
} else {
if (it.userData?.bloomAPI?.dim) {
it.userData.bloomAPI.dim();
}
}
}
// discard
if (it?.userData?.discard) {
it.visible = false;
}
if (it?.material?.userData?.discard) {
it.visible = false;
}
// disableBloom
if (it?.userData?.disableBloom) {
it.visible = false;
}
if (it?.material?.userData?.disableBloom) {
it.visible = false;
}
});
};
let renderToTexture = () => {
let { scene, clock } = get();
let dt = clock.getDelta();
let origBG = scene.background;
scene.background = dark;
efComposer.render(dt);
scene.background = origBG;
};
//
let restore = () => {
let { scene } = get();
scene.traverse((it) => {
if (it?.userData?.bloomAPI?.restore) {
it.userData.bloomAPI.restore();
}
if (it?.userData?.discard) {
it.visible = true;
}
if (it?.material?.userData?.discard) {
it.visible = false;
}
if (it?.userData?.disableBloom) {
it.visible = true;
}
});
};
this.renderTexture = () => {
let { gl } = get();
gl.shadowMap.enabled = false;
// bloom with occulsion image
setup();
setBloomSceneMat();
renderToTexture();
restore();
gl.shadowMap.enabled = true;
};
this.getTex = () => {
return efComposer.readBuffer.texture;
};
}
}
export class BaseLayer {
constructor({ mini }) {
let { get } = mini.now;
let resBase = new Vector2();
let dpr = get().gl.getPixelRatio();
resBase.copy({
x: get().gl.domElement.clientWidth,
y: get().gl.domElement.clientHeight,
});
resBase.multiplyScalar(dpr);
this.rtt = new WebGLRenderTarget(resBase.width, resBase.height, {
encoding: LinearEncoding, // sRGBEncoding,
generateMipmaps: false,
});
mini.onResize(() => {
resBase.copy({
x: get().gl.domElement.clientWidth,
y: get().gl.domElement.clientHeight,
});
resBase.multiplyScalar(dpr);
this.rtt = new WebGLRenderTarget(resBase.width, resBase.height, {
encoding: LinearEncoding, // sRGBEncoding,
generateMipmaps: false,
});
});
this.renderTexture = () => {
let { gl, camera, scene } = get();
// base image
let orig = gl.getRenderTarget();
gl.setRenderTarget(this.rtt);
gl.render(scene, camera);
gl.setRenderTarget(orig);
};
this.getTex = () => {
return this.rtt.texture;
};
}
}
export class Compositor {
constructor({ mini }) {
let { gl } = mini.now;
//
let quadMat = new ShaderMaterial({
//
uniforms: {
bloomDiffuse: { value: null },
tDiffuse: { value: null },
dpi: { value: gl.getPixelRatio() },
resolution: {
value: new Vector2(
1 / gl.domElement.clientWidth,
1 / gl.domElement.clientHeight
),
},
},
//
vertexShader: `
varying vec2 vUv;
void main (void) {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vUv = uv;
}
`,
fragmentShader: `
precision highp float;
uniform sampler2D tDiffuse;
uniform sampler2D bloomDiffuse;
uniform float dpi;
// // Converts a color from linear light gamma to sRGB gamma
// vec4 toSRGB(vec4 linearRGB)
// {
// vec4 cutoff = lessThan(linearRGB, vec4(0.0031308));
// vec4 higher = vec4(1.055)*pow(linearRGB, vec4(1.0/2.4)) - vec4(0.055);
// vec4 lower = linearRGB * vec4(12.92);
// return mix(higher, lower, cutoff);
// }
// // Converts a color from sRGB gamma to linear light gamma
// vec4 toLinear(vec4 sRGB)
// {
// vec4 cutoff = lessThan(sRGB, vec4(0.04045));
// vec4 higher = pow((sRGB + vec4(0.055))/vec4(1.055), vec4(2.4));
// vec4 lower = sRGB/vec4(12.92);
// return mix(higher, lower, cutoff);
// }
${FXAAFrag}
varying vec2 vUv;
void main (void) {
vec4 tDiffuseColor = texture2D(tDiffuse, vUv);
vec4 bloomDiffuseColor = texture2D(bloomDiffuse, vUv);
vec4 fxaaTDiffuseColor = FxaaPixelShader(
vUv,
vec4(0.0),
tDiffuse,
tDiffuse,
tDiffuse,
resolution,
vec4(0.0),
vec4(0.0),
vec4(0.0),
0.75,
0.166,
0.0833,
0.0,
0.0,
0.0,
vec4(0.0)
);
fxaaTDiffuseColor.a = tDiffuseColor.a;
vec4 outputColor = LinearTosRGB(fxaaTDiffuseColor);
outputColor.rgb += bloomDiffuseColor.rgb;
// linear to sRGB
gl_FragColor = outputColor;
// gl_FragColor.r += bloomDiffuseColor.r;
// gl_FragColor.g += bloomDiffuseColor.g;
// gl_FragColor.b += bloomDiffuseColor.b;
}
`,
});
// if (dpi == 3.0) {
// vec4 tDiffuseColor = texture2D(tDiffuse, vUv);
// gl_FragColor = vec4(tDiffuseColor.rgb, tDiffuseColor.a);
// } else {
// gl_FragColor = FxaaPixelShader(
// vUv,
// vec4(0.0),
// tDiffuse,
// tDiffuse,
// tDiffuse,
// resolution,
// vec4(0.0),
// vec4(0.0),
// vec4(0.0),
// 0.75,
// 0.166,
// 0.0833,
// 0.0,
// 0.0,
// 0.0,
// vec4(0.0)
// );
// // TODO avoid querying texture twice for same texel
// gl_FragColor.a = texture2D(tDiffuse, vUv).a;
// }
let fsQuad = new FullScreenQuad(quadMat);
this.render = ({ baseTex, bloomTex }) => {
let { gl } = mini.now;
if (gl) {
quadMat.uniforms.bloomDiffuse.value = bloomTex;
quadMat.uniforms.tDiffuse.value = baseTex;
quadMat.uniforms.resolution.value.x = 1 / gl.domElement.clientWidth;
quadMat.uniforms.resolution.value.y = 1 / gl.domElement.clientHeight;
fsQuad.render(gl);
}
};
}
}
export function SimpleBloomer({ api, gpi }) {
gpi.scope(({ sub: mini }) => {
mini.ready.gl.then(async (gl) => {
let scene = await gpi.ready.scene;
let camera = await gpi.ready.camera;
let base = new BaseLayer({ mini });
let bloom = new BloomLayer({ mini, api });
let compositor = new Compositor({ mini });
gpi.onLoop(() => {
if (api.now.renderMode === "fast") {
scene.traverse((it) => {
if (it?.userData?.bloomAPI?.suspense) {
it.userData.bloomAPI.suspense();
}
});
gl.render(scene, camera);
} else {
base.renderTexture();
bloom.renderTexture();
compositor.render({
baseTex: base.getTex(),
bloomTex: bloom.getTex(),
});
}
});
});
});
return null;
}
import { Canvas } from "@react-three/fiber";
export function Starter({ children, reducedDPI = 2 }) {
if (
typeof window !== "undefined" &&
window.innerWidth >= 500 &&
"ontouchstart" in window
) {
reducedDPI = 1;
}
return (
<div className="h-full w-full">
<Canvas
dpr={[1, reducedDPI]}
gl={{ antialias: true }}
style={{ width: "100%", height: "100%" }}
// performance={{
// current: 1,
// min: 0.1,
// max: 1,
// debounce: 200,
// }}
>
{children}
</Canvas>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment