-
Notifications
You must be signed in to change notification settings - Fork 215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[enhancement] Isolate ProgramData from Program for allow reuse GL Program instance #139
Conversation
I agree that we need a way to reuse compiled shaders. But it's wrong way to cache |
@RAX7 Ogl not support multiple contexts. It already hold VAO, texture, framebuffers. If contexts will changed (after loose) - nothing will working. Yep, problem that cache stored in program by sources only - easy can be moved to renderer instance or by GL reference (How in your PR) (will move to, valid notice) By normal all native pointers should be stored in renderers instances by uuid instead of regular classes. This has some benefits:
But this is breaking changes and huge codebase. @gordonnl what you think? |
No, it does. Because we should pass gl instance to most items constructors, like |
@RAX7 My PR is bugged, it PR and should be fixed of course. I meant about:
When you can use SAME nodes in different contexts. This can automatic fix #74 |
Wich NODES do you mean? |
@RAX7 and all resources: Textures, Programs, RenderTargets, Geometries. Should be like this: // scene nodes should be context-free
const scene = new Transform();
const geometry = new Box();
const program = new Program({
vertex,
fragment
});
const cube = new Mesh({ geometry, program });
cube.rotation.y -= 12;
cube.rotation.x -= 12;
cube.position.set(0, 0, 0);
cube.setParent(scene);
const camera = new Camera({ fov: 35 });
camera.position.set(0, 0, 8);
camera.lookAt([0, 0, 0]);
// create renderers for each context
function create(selector, antialias = false) {
const canvas = document.querySelector(selector);
const renderer = new Renderer({ canvas, antialias });
const width = window.innerWidth / 2;
const height = window.innerHeight;
renderer.setSize(width, height);
camera.perspective({ aspect: width / height });
return () => renderer.render({ scene, camera });
}
const r1 = create('#canvas-1');
const r2 = create('#canvas-2', true);
r1();
r2(); For ex: GLTF is huge, and load ant parse it for multiple instances - bad idea. Ideal use a single loader and share data between contexts. Thanks for notice. |
@eXponenta nice, now demo is works!
To implement that idea you need create something like a PIXIJS does. When program is create shaders does not compiling. Its compiles only before render try to get program from cache. And all this changes are:
as you sed before |
I already can move compile from constructor to Program.use method and call it before each use, and pass GL from program to it. |
Yes, then you solve problem you get another one. And that's why I prefer to keep things simple as possible. I don't need render-context-free classes, I don't need a super smart system with cache everything. I wish just to have cheap and fast |
Why need this?
Sometimes needs to use multiple instance for same shader code, but with different uniforms (textures, color, any other data) which can't passed by attributes;
This PR split Program and ProgramData, now ProgramData store only info that needed for program usage.
Program now is like Material - store instance-specific values like uniforms or state.
You can spawn a lot of Programs from same shader code that with different uniform and state combination (see updated example).
Other benefits - we can easy change a ProgramData in program without update program reference in each mesh instance.
When this can be used? For example, when need use different shaders for each pass, like ShadowMap pass. You can change programData field to specific ProgramData instance for specific Program and shader will be replaced for each references automatically, but uniform and state wont changed.