Is there a way to implement "backbuffer" textures? #1495
Unanswered
mikeylemmon
asked this question in
Q&A
Replies: 1 comment 6 replies
-
That's a really interesting question and I would love to explore this further. Below is a simple backbuffer example in Skia. There are a couple of things here:
import React, { useRef } from "react";
import type { SkShader } from "@shopify/react-native-skia";
import {
FilterMode,
MipmapMode,
Skia,
SkiaView,
TileMode,
useDrawCallback,
} from "@shopify/react-native-skia";
import { Dimensions } from "react-native";
const bufferA = Skia.RuntimeEffect.Make(`
uniform vec3 iMouse;
uniform shader iChannel0;
half4 main(vec2 fragCoord)
{
float distance = length(fragCoord.xy - iMouse.xy);
if (distance < 9.0 && iMouse.z > 0.01) {
return vec4(1.0, 0.0, 0.0, 1.0);
}
return iChannel0.eval(fragCoord);
}`)!;
const { width, height } = Dimensions.get("window");
const offscreen = Skia.Surface.Make(width, height)!;
export const Backbuffer = () => {
const backbuffer = useRef<SkShader>(
Skia.Shader.MakeColor(Float32Array.of(0, 0, 0, 1))
);
const onDraw = useDrawCallback((canvas, info) => {
const touch = { x: 0, y: 0, z: 0 };
const lastTouch = info.touches[0];
if (lastTouch) {
touch.x = lastTouch[0].x;
touch.y = lastTouch[0].y;
touch.z = 1;
}
// 1. Draw to the backbuffer
const paint = Skia.Paint();
paint.setShader(
bufferA.makeShaderWithChildren(
[touch.x, touch.y, touch.z],
[backbuffer.current]
)
);
offscreen.getCanvas().drawPaint(paint);
// 2. Swap
backbuffer.current = offscreen
.makeImageSnapshot()
.makeShaderOptions(
TileMode.Decal,
TileMode.Decal,
FilterMode.Nearest,
MipmapMode.None
);
// 3. Draw Result
const frontPaint = Skia.Paint();
frontPaint.setShader(backbuffer.current);
canvas.drawPaint(frontPaint);
});
return <SkiaView style={{ flex: 1 }} onDraw={onDraw} />;
}; |
Beta Was this translation helpful? Give feedback.
6 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Many graphics tools and libraries provide a mechanism to expose to shaders a feedback "backbuffer" texture that contains the contents of the previous frame (for example, gl-react provides the "backbuffering" prop on the Node component). This enables the implementation of many time-based effects, as well as physics-based simulations and abstract simulations such as Conway's Game of Life:
Under the hood, backbuffers are usually implemented by creating two framebuffer objects and two roles for them, a draw destination and a backbuffer, that are swapped each frame so that the buffer that is drawn to in frame N becomes the backbuffer in frame N+1 and visa versa. (Here is where the framebuffer roles are swapped in gl-react's Node implementation: https://github.com/gre/gl-react/blob/b116482/packages/gl-react/src/Node.js#L1139)
Is there currently a way to implement backbuffers in RN Skia? I've looked into using
Skia.Surface.MakeOffscreen
(as mentioned in #1359), but it's unclear to me how to bind the offscreen surface's framebuffer to a shader uniform.Any help or insight appreciated. Thanks!
Beta Was this translation helpful? Give feedback.
All reactions