Using Three.js to render images on several canvases with WebGLRenderer from various perspectives

I have encountered a challenge where I need to use only 1 WebGLRenderer, but have multiple camera views that should be displayed on unique canvases. In the current setup, I have 9 views placed in one canvas, each with distinct cameras, scenes, and meshes which are then drawn onto separate canvases using the ctx.drawImage method. However, this method is too slow and does not yield the desired frame rate of 60+ fps.

Is there an alternative solution to avoid using the sluggish drawImage method? Are there any ways to optimize or accelerate this entire process?

Your help is greatly appreciated, and you can find the example code below:

http://jsfiddle.net/QD8M2/

<!doctype html>

<html lang="en>
<head>
    <meta charset="utf-8">

    <title>Three.js Test</title>

    <style>
        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    </style>

    <!--[if lt IE 9]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
</head>

<body>
    <script src="./three.min.js"></script>
    <script>
        var renderer;
        var windowWidth, windowHeight;
        var numberMeshes = 1;
        var dpr = window.devicePixelRatio || 1;

        var viewDimensions = {x: 3, y: 3};
        
        ...
    </script>
</body>
</html>

Answer №1

After some trial and error, I managed to come up with my own solution. It may not be as advanced as prabindh's answer, but it did the job for me.

The approach I took was using a WebGLRenderTarget to render each view or scene onto the renderer and then extracting the pixels using readPixels onto a canvas. Although I attempted to utilize web workers for better performance, I encountered difficulties integrating them smoothly with image writing. Below is the code snippet:

If prabindh had something entirely different in mind, I am open to suggestions on how to enhance this process's speed and efficiency for my specific use case.

// Your modified code goes here... 
// Make necessary changes and improvements

Answer №2

Following a discussion in the comments, utilizing FBO with varied perspectives and using these textures as input for positioning in different views may be appropriate for your situation. Please review. It's important to note that this method does not involve drawing to a buffer, then reading pixels back, and applying them to a canvas.

EDIT1: Including pseudocode Using Three.js

Create an offscreen target:

rtTexture = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, ..);

Create a screen, material, and mesh:

mtlScreen = new THREE.ShaderMaterial({ uniforms: { tDiffuse: { type: "t", value: rtTexture } },

mtl = new THREE.MeshBasicMaterial({ map: rtTexture });

mesh = new THREE.Mesh(plane, function(rtTexture));

scene.add(mesh);

Render to the offscreen first, then to display:

renderer.render(sceneRTT, cameraRTT, rtTexture, ..);

renderer.render(scene, camera);

Refer to the standard three example to access the full code - https://github.com/prabindh/three.js/blob/master/examples/webgl_rtt.html, and I shared a brief presentation on this at

Approach With GLES2:

Simple setup for FBO with GLES2 (minor adjustment to WebGL):

  •  glGenFramebuffers(NUM_FBO, fboId);
     glGenTextures(NUM_FBO, fboTextureId);
     glGenTextures(1, &regularTextureId);
    

Next is the setup for drawing to offscreen buffers:

  •       GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
            GL_CHECK(glBindTexture(GL_TEXTURE_2D, fboTextureId[i]));
            GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, globals->inTextureWidth, globals->inTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    
            GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, fboId[i]));
            GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTextureId[i], 0));
    

Then draw to the offscreen buffer:

  •         //Bind regular texture
            GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
            GL_CHECK(glBindTexture(GL_TEXTURE_2D, regularTextureId));
            add_texture(globals->inTextureWidth, globals->inTextureHeight, globals->textureData, globals->inPixelFormat);
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
             //Draw with regular draw calls to FBO
            GL_CHECK(_test17(globals, numObjectsPerSide, 1));
    

Now use this as a texture input, and draw to the regular display:

  •         GL_CHECK(glBindTexture(GL_TEXTURE_2D, fboTextureId[i]));
    
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
            //draw to display buffer
    
           //Get back the display framebuffer and unbind the FBO
            GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
    

https://github.com/prabindh/sgxperf/blob/master/sgxperf_test17.cpp

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide to directing a user through an Ajax call to a particular Controller and action

Here is a custom JavaScript function that updates data when the Update button is clicked. function UpdateData() { var obj = { "testData": $("#hdn_EditdsVal").val(), "feature": $("#hdn_EditdsVal").val() }; $.ajax({ url: ...

How can I display a JSON object as a table in Sinatra?

When working with Sinatra, an Ajax action returns a JSON object. I am trying to display this data in a table within my view. The JSON object includes a list of items that need to be shown. One approach is to render the table using JavaScript. This would i ...

A more effective method for restricting the properties of a field in an aggregate query

In my MongoDB query, I am attempting to use the aggregate function to fetch data from one collection while limiting the amount of data retrieved from another collection. Here is the code snippet that I have come up with: getFamilyStats: function (req, res ...

Adding the most recent version of jquery causes the webpage to malfunction

Currently, I am facing a challenge on a website that has an outdated version of jQuery (1.7.2) included in the header. In order to use a plugin that requires the latest version of jQuery, I tried linking the newer version (2.1.3) in the footer. However, j ...

Switch the angular attribute by clicking on ng-click

I have a Google Map set up with markers that I need to switch on and off. <marker id='{{marker.id}} 'visible="{{ condition ? 'true' : 'false'}}"> </marker> Additionally, I have created a button to control the v ...

Passing a deconstructed object as a parameter for a function

I'm having trouble understanding the parameter const Posts in the code snippet below. As a newcomer to node/React, I'm not sure if it's a destructured parameter object or just an object being passed as a parameter. The functions getPosts an ...

Display clickable buttons beneath the Material-UI Autocomplete component

I want to place buttons ("Accept" and "Cancel") below the MUI Autocomplete element, and I am trying to achieve the following: Limit the Autocomplete popover height to display only 3 elements. To accomplish this, pass sx to ListboxProps Ensure that the b ...

Determining when all $http requests have completed in AngularJS

After running multiple $http calls, I need to trigger an event only when all of them have been processed. Additionally, I must be informed if any call has failed along the way. Despite attempting solutions found on stackoverflow, such as using an intercept ...

Adding a query parameter to a dynamic route in NextJS

In my NextJS application, I have implemented a language selector that is displayed on every page. The goal is to change the current URL by adding a query parameter lang=en when a new language is selected. The function responsible for updating the URL look ...

Pulling information from a database query to store it within a JavaScript variable

Using Ajax/JQuery, I successfully send the variable ($name) from page1.php to page2.php without refreshing the page. When the submit button is clicked, it sends me the var $name effectively. Additionally, in my JavaScript library for charts (AmCharts), the ...

disable the form submission function in dropzone when buttons are clicked

Dropzone is being utilized on my page in the following manner alongside other input types such as text and select dropdowns: <form name="somename" method="post" action="/gotoURL" form="role"> // Other form elements here <div id="dropare ...

Issue: Unable to find a compatible version of chokidar. Attempted chokidar@2 and chokidar@3 after updating npm to version 7.*.*

After using ejected CRA, it compiled successfully but then broke with the following error. The issue started to occur after updating npm from version 6 to 7. You can now view webrms in the browser. Local: http://localhost:3001 On Your Netw ...

Designing a menu inspired by the layout of Google Plus

I am attempting to create a responsive menu that behaves similarly to the one on Google Plus. In this menu, main options are either added to or removed from the "more" dropdown as the window is resized. Here is the current appearance of my menu: Below is ...

Transferring information between HTML pages using JSON and jQuery

After reviewing the topics, I was unable to find a complete answer. My objective is to populate a drop-down menu with text from another HTML file. Both HTML files are located on localhost. It is mandatory for the data to be in JSON format. Initially, I a ...

JavaScript causing Axios network error

Recently, I've started exploring the combination of axios and stripe in my project but unfortunately, I have encountered some challenges. Whenever I attempt to initiate a post request using axios, an error pops up which looks like this: https://i.sta ...

Querying the database to check for the presence of a file in a .js file on Google App Engine

I'm currently working on implementing an upload button for users to upload files to our storage system using Google App Engine with Python, as well as HTML and JavaScript for the views. To achieve this, we have an HTML file and a.js script that promp ...

:visible fails to function following the submission event

Here is my code snippet: http://jsfiddle.net/Z9qP5/1/ I am trying to fadeOut my form once the user has submitted their email. However, I am facing an issue where I cannot capture the submit event. What I want is for the form to be hidden when the success ...

The expiry date of the cookie remains unchanged

When attempting to create a cookie and specify an expiration date, I am encountering an issue where it remains as "Session". This problem is occurring in Google Chrome. I'm looking for insights on what might be causing this behavior. The code snippe ...

Comparing unique values between objects in JavaScript with varying keys

I'm facing a peculiar issue that I can't seem to solve. I have two variables named nft and web3.givenProvider. Both of them have an address value of "0x0000000000000", but they are stored under different keys - nft is under .seller and ...

What's the deal with THREE.ImageUtils these days?

Currently in the process of updating outdated JavaScript code using three.js for textures. Specifically looking to improve the second line of code below. var groundColor = new THREE.Color(0xd2ddef); var groundTexture = new THREE.ImageUtils().generateData ...