Skip to content
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

Multiple OBJ models rendering #9

Closed
EtagiBI opened this issue Nov 28, 2017 · 106 comments
Closed

Multiple OBJ models rendering #9

EtagiBI opened this issue Nov 28, 2017 · 106 comments

Comments

@EtagiBI
Copy link

EtagiBI commented Nov 28, 2017

Hello,

First of all, I would like to thank you for all your efforts! Your project seems to be the only one alive project dedicated to Three.js photorealistc rendering.

As for my question, is it possible to render multiple OBJ models with your PTR? My friend and I are working on a Three.js based room planner as our university project. We have a bunch of textured furniture models with different material determined via corresponding MTL files. Is this feature supprted by PTR? As I can see from your demos, at the moment PTR works with simple shapes only.

@erichlof
Copy link
Owner

Hello @EtagiBI

Thank you for posting your question here - I'm sure there are others out there who are wondering the same about the ability to load multiple OBJ files, and possibly MTL files as well.

The short answer is unfortunately, not at the moment. I currently have a demo that loads a single OBJ file. So my path tracer has the raw ability to load a list of vertices/faces in OBJ file format, and path trace the mesh relatively quickly. However that Crane model in the demo only has 36 triangles. Even that amount lowers the frame rate on my laptop from 60 to 40 fps. Things get worse if you, for instance, go into the HTML source code and comment out the Crane model and choose another listed model with a higher poly count. So if you and your friend are trying to load rooms full of thousands or even hundreds of triangles, the frame rate will probably slow to a crawl, like 1 or 2 fps, or even lose the WebGL context. Users would not be able to smoothly look around your room with their mouse, and would probably get frustrated.

Now for the long answer, if you're interested ;-)

When I started this project I was naive in thinking that if I could make geometric mathematical shapes render at 60 fps, then I'll just eventually throw a list of triangles at it and it would be the same. But sadly, checking rays against every triangle in a detailed mesh really adds up. And that's just for the initial raycast - you have to multiply that cost by 4 if you want to bounce those same rays around the room to get global illumination. So I looked into acceleration structures like grids, KD trees, and the BVH - the latter seemed to be the preferred choice for ray tracing and path tracing, so I ported a BVH builder in C++ over to Javascript. This seems to help a lot, BVH attempt , but the problem is that WebGL 1.0 does not support dynamic indexing of arrays during a loop, such as correctBranch[x]. In WebGL 1.0, that 'x' must be a constant like '2' or a predefined value. That means that I can't prune large parts of the tree, which is the whole point of having an acceleration structure in the first place. When WebGL 2.0 is supported inside three.js (hopefully soon), then I can revisit the BVH with dynamic indexing allowed, and even look into the LBVH which uses Morton codes and bit manipulations (allowed only by WebGL 2.0), which can rebuild the entire structure on the GPU for a scene of moving, dynamic triangles - every frame.

I would love to be able to list a bunch of meshes like you and your friend want to do in the room scenes, and have it all just work. But getting it to run smoothly is the most difficult aspect of ray/path tracing I'm finding out. Traversing the BVH is not too hard to understand, and it can be done in a tight loop inside a GPU shader in 30 lines or so. What is difficult to grasp and implement on the GPU, is the BVH builder, which must quickly load thousands of triangles into texture memory, create bounding boxes and indices for all of those triangles, and then order them in some efficient fashion to be examined and pruned by the tracer. Unfortunately, GPU BVH builders and source code (even in CUDA, let alone WebGL) are poorly documented and explained. It's no coincidence that a lot of cutting-edge research has been done in this area, and if good results are found, they are assimilated into existing renderers that might be behind patents and not available for public viewing of the GPU source code. However, maybe this will change with more people out there like me trying this stuff out on their own, and posting it online for all to learn from.

It's frustrating because I know interactively rendering large amounts of triangles is possible, even inside seemingly low WebGL. For instance I found this cool piece of software, which is similar to my project, but has much more capabilities in terms of rendering large meshes: Antimatter . Scroll down and hit the 'Launch Prototype' button. Then you can choose from a list of large meshes. If they can do it in the browser with a BVH, it has to be possible. I would have said you guys should go with that for your project, but it looks like it is going to be for purchase only, and not open source - plus I don't know how deep into needing three.js in your project you already are.

I wish I could be of more help to you both, I hope you can find a different approach or a workaround in the meantime. If you would like to ask anything else or need clarification or advice, please don't hesitate.

-Erich

@EtagiBI
Copy link
Author

EtagiBI commented Nov 29, 2017

Wow, thanks for a thorough reply!

I forgot to mention that we want to render our scenes server side, not in real-time. The whole plan looked like this:

  1. We create a scene in our "home-made" three.js 3D planner
  2. We press some "Render" button that throws our ticket in a rendering queue on server
  3. We patiently wait...
  4. We receive a rendered photorealistic image!

Is it possible? I clearly understand that real-time rendering of multiple textured models is really heavy for resources.

@erichlof
Copy link
Owner

Hello @EtagiBI
Ah, so offline rendering while you wait is ok. Mmm, I hadn't imagined this kind of use-case yet for a browser path tracer. I actually need to get some sleep, it's late here where I am. But let me think about it for a little bit and if I can't do a demo myself with the tools I have in this repo, I may be able to point you in the right direction using a javascript path tracer that can handle any amount of mesh data, but maybe without fancy or crafty GPU shaders to make it go real time, since you don't mind it being an offline rendering.
I'll get back to you soon, thanks!

@erichlof
Copy link
Owner

erichlof commented Nov 29, 2017

Hi again @EtagiBI

After thinking about it for a while, unfortunately I don't think the tools that I have developed here can help you at the moment. What you are needing is a robust loader, simple editor, and an offline beauty renderer. What I have here currently is a non-robust, simple shape renderer that goes as fast as possible so you can move and look around in real time, but still have correct global illumination effects. I started the project with the latter in mind and geared every line of code towards that purpose. I would have to essentially start over with what you have in mind to really do it right, instead of trying to hack something robust (loading .obj files, textures, etc.) into the blazing fast GPU path tracer that was made for different purposes.

But I really like the idea that you have, which is, if I understand correctly, to use three.js and the browser as a visualizing tool to load .obj files into a simple editor where you can click and move furniture around a virtual room using the three.js default WebGL renderer at 60fps. Then when you are happy with how the room looks, you hit 'Render' and it dumps all of that data (a big list of triangles, vertex normals, texture uv's) into the path tracer, which ray casts against those triangles, finds the closest intersection, looks up the normal and uv data for that correct triangle, and colors that pixel. When all pixels have been calculated, then it saves the final render as a .png or something. That part would take several minutes without acceleration structures, but you mentioned that you don't mind waiting offline for it to finish the calculations. I might go off and attempt a side project of my own that loads a whole scene of .obj files and then renders offline because this sounds like a neat project idea, but mine would be minus the editor part, that is a whole other tool set that would take weeks to develop - editor .

It just occurred to me that someone has already done what you are wanting: Ben Houston and his Clara.io project. Here's the link: Clara.io Ben is a nice fellow who has contributed a lot to the three.js code base. He wants his browser based editor/renderer/modelling software to be able to compete with 3dsMax, Maya, Blender, etc. I hope he and his team succeed because having the ability to be online and collaborating real time while using a sophisticated 3D modeling package is a great idea. In a nutshell, his software loads meshes of any file type (.obj, .fbx, etc), uses three.js renderer in real time to drag, reshape, resize the scene and meshes, then you hit fast preview and the sophisticated V-Ray rendering farm jumps into action. If you like the preview, you hit full render, wait, then hit save image and you're done. It's free to try out, you might give it a go - if only to get some ideas for your project.

Sorry I couldn't be of more help with my tools in this repo, but hopefully you have an idea of what needs to happen in your software, and hopefully I at least pointed you in the right direction. If you like, you can post any future findings or breakthroughs, or links to your project here so we can all benefit.

-Erich

Edit: just found a perfect resource that does what you are wanting and is open source: XRay
Hope this helps!

@EtagiBI
Copy link
Author

EtagiBI commented Dec 1, 2017

Hello @erichlof!

I'm sincerely impressed by amount of useful information given by you. Thank you very much!

I'll try to keep this topic up-to date.

@erichlof
Copy link
Owner

erichlof commented Dec 1, 2017

Hi @EtagiBI ,

Glad to be of help, sorry I couldn't have my existing project just work out of the box for what you wanted. However, you have inspired me to start planning ahead and working towards being able to call the THREE.OBJLoader on various meshes, and then they get their data get saved to a texture to be consumed by the GPU and path traced. Earlier today I just figured out how to let the THREE.OBJLoader do all the .obj file parsing work (I task I kind of understand but not completely), and then 'hijack' the newly created THREE.Mesh and open it up and read and save its geometry data to a texture. Next is to try to do the same with materials data from a .mtl file. I'll post a short demo here soon!

Thanks :)

@erichlof
Copy link
Owner

erichlof commented Dec 22, 2017

Hi @EtagiBI
Just wanted to give you an update of my progress with this issue. I didn't want you to think I had forgotten about you and this feature request! :) I have figured out how to use three.js's THREE.OBJLoader (I was using a less-robust custom one that I had ported from C++ before) and I am now able to hook into the resulting mesh and save its entire triangle data to a THREE.DataTexture, which can be saved and quickly loaded onto the GPU for use with the path tracing engine. Demo and its Source Code

I understand the .obj and .mtl file formats now (they were well designed which is why they have lasted so long I guess! ), but I'm trying to decide how to retrieve the material data and then make physical ray tracing materials out of them. You can see from the demo, I just assigned a matte bright purple color to all the triangles of the crane origami .obj model. But suppose there was an accompanying .mtl file that said they wanted the crane's neck to be transparent blue, the wings to be shiny silver, and the body to be matte gray or something? For the path tracing engine to use that data, it needs to have its physical reflectance properties as well as a color and shininess or color and transparency. So the matte would be the easiest, I could just assign that to be Lambertian diffuse in my engine, the shiny one would have to have a metalness flag saying if it is a metallic specular object, or just a shiny piece of plastic. The transparent one would need an Index of Refraction (IoR) saying how much the rays should bend when they enter a transparent surface like glass, clear coat plastic, or water.

So I am kind of going back and forth as to how I should implement the materials loading part of all this. I'll give you more updates as I work towards a solution. If I can eventually get the BVH working with WebGL 2.0 supported in three.js, then all objects will load and render in real time!

@EtagiBI
Copy link
Author

EtagiBI commented Dec 26, 2017

Excellent news!
As far as I understand, all materials have these specific characteristics (light reflection, light absorbtion, etc.) within MTL file. We've managed to add dynamic lighting in our editor, so models with different material characteristics look different now.

Since three.js has obtained shader support, we're trying to implement native shadows for models.

@FishOrBear
Copy link

@EtagiBI Hi, How is your project going?

I also want to do similar projects. Any suggestions?

I understand a lot of open source renderers, and I'm ready to try Blender Cycles now.

@EtagiBI
Copy link
Author

EtagiBI commented Mar 28, 2018

@FishOrBear Yes, we decided on Blender Cycles as well. Render quality is great, but it took a while to adjust parameters.

@FishOrBear
Copy link

@EtagiBI
Did you start using it?

I understand that some of the Cycles documentation is missing.

I found that the mitsuba document is sound. I am now considering what rendering engine to use.

@MEBoo
Copy link

MEBoo commented Sep 4, 2018

Hi @erichlof any news about?

I'm very interested in your project... but to do online client background rendering (no realtime) of Three.js scene created online loading OBJs and applying custom materials dinamically (no MTLs involved).

It would be nice having more OBJs and three.js support, before Febrary 2019...

Thankyou

@erichlof
Copy link
Owner

erichlof commented Sep 4, 2018

Hi @meblabs
I'm sorry but I'm kind of at a stand-still with OBJ rendering until the folks at three.js implement WebGL 2.0 support. In order to render larger scenes or multiple OBJ files, I need to physically load the triangle data onto the GPU, and the only way to do that currently is through a data texture. I have successfully done it with one small OBJ file, see the simple OBJ demo - but as soon as I try loading multiple files or 1 large OBJ file (the Utah teapot with 1000 triangles, for instance) the renderer slows to a crawl and crashes or just fails to compile.

Therefore I needed some kind of data acceleration structure for randomly sorting through all those triangles, and the only way to do that is to have random access into large arrays, which is not supported by WebGL 1.0 (which is still only supported by three.js). WebGL 2.0 brings with it the possibility to look up data randomly inside an array through the GPU fragment shader, which I absolutely must have in order to continue with that part of the project.

If wait-time for rendering is not a concern, you could go with a CPU renderer, which is not accelerated of course, but definitely has the capability to sort through huge amounts of OBJ triangle data pretty quickly. It would just render a static image though, which is not the focus and direction of my project.

The only other alternative I can think of is that you create something with three.js, use their converter to convert the entire scene to a readable file by a production renderer, like Octane for Cinema4D, Cycles for Blender, V-Ray for Clara.io, etc. and hit the render button inside their software. It should be the best of both worlds, able to be accelerated somewhat with their proprietary acceleration structure, and able to handle huge amount of scene data through streaming.

Sorry I can't be of more help. Best of luck to you with your project. Please let us know if you find a temporary solution with other software, as I have had some similar questions and requests for larger amounts of data rendering.

@mrboggieman
Copy link

mrboggieman commented Sep 4, 2018 via email

@MEBoo
Copy link

MEBoo commented Sep 5, 2018

Thanks @erichlof ... so let's wait for a three.js upgrade to WebGL 2.0

Exporting data to another offline renderer is not an option, since I need to render client side and online.

But thankyou for your explanation.

When you say that the scope of your project is not a static rendering, please consider that your work is the best I've seen here, speaking about pathtracing etc., the tech you built can be used in a real context, so I would consider to simply generate a client-side hi-res and quality (but slow) render, other then the super fast real-time rendering that is awesome but more for science.

So I hope you'll consider my suggestions when the three.js upgrade become ready...

See you next months ;)

@MEBoo
Copy link

MEBoo commented Sep 5, 2018

@mrboggieman thankyou! But I've already seen that project... the problem is that it'isnt opensource... I can't find a repository.

And the work done by @erichlof seems better, regarding the final render quality after many samples... and AntiMatter is not Three.js based :(

@erichlof
Copy link
Owner

erichlof commented Sep 6, 2018

@meblabs
Thank you for the kind words! I will definitely keep the quality static render scenario in mind once I get the BVH going with WebGL 2.0 support from three.js, etc. Speaking of AntiMatter, yes unfortunately that renderer is not three.js based, nor is it open source from what I can tell. I have looked extensively through the author's GitHub repo's and his website but there is nowhere to view his source code for that particular project. However, one glimmer of hope: I was able to right-click and 'view page source' while running the AntiMatter browser app, and I was able to piece together what looked to be a working BVH using WebGL 1.0. Mind you it is in minified/compact mode, so all the functions are like one letter or 2 letters long, lol. So it can be done, I just have to try to piece it together. I've already made some headway with his GPU fragment shader source. It looks like he implemented some crafty workarounds to sidestep the random array indexing problem. It's ugly and wasteful but it works! ;-)

I'll let everyone know if I can gain any ground with WebGL 1.0 while I'm waiting for WebGL 2.0 support.
Thanks again,
-Erich

@MEBoo
Copy link

MEBoo commented Sep 6, 2018

@erichlof wow that's great!
I've also checked his code and saw that it is minified... but I don't have many skills about :(

if I were you, I'd wait for webgl 2.0, but with WebGL 2.0 it would be awesome to also have a working PBR shader, simply configurable (like the one included in Three.js), and that supports at least a simple texturing method... Let me know if it is possible or a dream!

I can wait some months :)

Thankyou again!

@erichlof
Copy link
Owner

erichlof commented Sep 6, 2018

@meblabs
Hi, yes it is possible to incorporate PBR materials - they would need to be set in the triangle data list and loaded onto the GPU as a data texture. Currently I only have positional data for each triangle vertex packed in a texture, so something like
dataTexture[0,0].r = 270.01; dataTexture[0,0].g = -65.86; dataTexture[0,0].b = 483.2;
And that defines where the triangle vertex is located in model space, XYZ = .r, .g, .b

To get PBR data on top of that, we would need to pack the data into a larger structure inside the texture, such as:
dataTexture[0,0].r = 270.1; dataTexture[0,0].g = -65.86; dataTexture[0,0].b = 483.2; dataTexture[0,0].a =43.9;
dataTexture[1,0].r = 124.7; dataTexture[1,0].g = 54.8; dataTexture[1,0].b = -843.1; dataTexture[1,0].a =675.0;
.rgb is first vertex XYZ, .a .rg is second vertex XYZ, .b and .a is third vertex XY
dataTexture[2,0].r = 453.8; dataTexture[2,0].g = 1.0; dataTexture[2,0].b = 0.0; dataTexture[2,0].a =
0.0;
(the .r channel here is continuation of the previous vertex list vertex Z, because 9 / 8 has a remainder of 1 (annoying, right?), .g .b. a. defines the usual rgb diffuse color, so a red triangle.

dataTexture[3,0].r = 1.0; dataTexture[3,0].g = 1.0; dataTexture[3,0].b = 1.0; dataTexture[3,0].a = 0.5;
still on the same triangle, now it's the PBR stuff like specularColor.r, .g, .b, and a 'roughness' value

dataTexture[4,0].r = 0.0; dataTexture[4,0].g = 1.0; dataTexture[4,0].b = 0.5; dataTexture[4,0].a = 0.25;
still the same triangle, but finally we finish up with PBR stuff like 'metalness', Index of Refraction, clearCoat IoR, clearCoat roughness.

So it can be done, but as you can see there needs to be a lot more texture data slots (around 20) for each triangle. The final texture size would need to be the number of triangles in the model, times 5 rgba slots per triangle. So roughly calculating, if we had a 10,000 triangle model, that's 50,000 .rgba texture slots (200,000 total floating-point data entries packed in). Which seems like a lot, but most cell phones even can handle a 4096x4096 .rgba texture, so that's 16,777,216 available texture elements, each with their own .rgba channels (4 values for each texture element), so 67,108,864 possible triangle data entries packed into 1 texture.

edit : argh, I forgot uv texture coordinates need to be specified for each of the 3 vertices, so that's 6 more data numbers to pack in, maybe pad it to 8 numbers (2 .rgba texture elements) to be memory look-up effecient, and use the 2 remaining slots for Texture ID (which texture to use), extra texture info, etc.

So I kind of know how I would approach it, but getting materials to change on the fly inside some kind of material editor would take a lot more work and know-how. That's why they have teams of 10, 20 or more working on OTOY Octane, Blender Cycles, etc. I don't know if I could do all that alone, it isn't really part of the scope of this project. But it definitely is possible and has already been implemented with more sophisticated renderers. Hope that helped! :)

@MEBoo
Copy link

MEBoo commented Sep 6, 2018

@erichlof wow seems a little complicated...
I've not studied this yet... so the problem is how to send data to the GPU to elaborate it with a Fragment Shader? With WebGL2 there is no other new fancy way?

But when your base tech will be ready, I can work on like a monkey and you could tell me what to write :D (and I may pay other monkeys to help me)

@erichlof
Copy link
Owner

erichlof commented Sep 6, 2018

@meblabs
Yes it is pretty complex unfortunately. The easiest part was getting the basic path tracer to work. There are many tutorials out there such as the ones on ScratchAPixel and ShaderToy, and of course Kevin Beason's smallpt in C++, which is where I started. In a couple hundred lines of code you can have a decent looking path tracer. When you are rendering simple shapes like spheres, it's great, but as soon as you start trying to render large triangular models, everything slows to a halt or crashes. Then you realize an acceleration structure is needed to speed up rendering and load all those triangles. I have yet to find a full tutorial for streaming acceleration structure data (like a BVH - bounding volume hierarchy) to the GPU. There aren't even decent tutorials on how to create the data structure in the first place, let alone sending it to a fragment shader as a texture. I was lucky enough to find a C++ CPU BVH example here on GitHub and I ported it successfully (this is what is used on my current model rendering demos). But there is almost 0 information on how to do that on the GPU, and in WebGL (1.0 or 2.0). Then there's the problem we were discussing about how to store all that material data for each triangle made in a 3d modelling program. Again, no tutorials on that as a GPU texture out there on the internet.

I'm still looking at the AntiMatter source - I might post some of it here - I have gone in and renamed the minified variables and functions so instead of reading 'float m=m0(g, h);' it reads 'float result = calculateFresnel(vec3 intersectionPoint, int material_ID);' I'm still looking into it. :)

@MEBoo
Copy link

MEBoo commented Sep 7, 2018

@erichlof thanks and good work... let me know if I have to do something in future ;)

@erichlof
Copy link
Owner

erichlof commented Sep 9, 2018

Hi @meblabs and all,
As promised here is the antimatter glsl shader source in its original minified form: antimatter.min.glsl It was all smashed together on one long line of code, so I did a quick document format, adding spaces and line returns for some readability.

And after going through his code line by line, here is my decompressed version: antimatter.glsl I reverse-engineered and added clear, meaningful variable names and function names, for maximum readability.

There are a lot of similarities between his path tracing shader and mine here on my repo. I added a comment to the function
StackElement_data getStackElement_byIndex(const in float ix)
indicating this is how he did the workaround for the WebGL 1.0 limitation of no dynamic array indexing.

I am in the process of decompressing the index antimatter.js file that does all the WebGL initialization stuff and creates the BVH to data texture for GPU consumption. This part is even more complicated than the shader intersectBVH function. Creating the acceleration structure is always more difficult because you have to order all of the thousands (or millions) of triangles, vertex data, and material data, sort them, and compress them onto a texture in a meaningful way. But hopefully by studying his source I can make some headway. ;-)

@MEBoo
Copy link

MEBoo commented Sep 10, 2018

@erichlof ahaha great work!
only 500 lines of code to render the reality, awesome!
Do you think that the workaround has the same performance as the webgl 2.0 will have?

Regarding BVH, you should already have your implementation done, right? Or yours is not for traingles, but for primitives only?

@erichlof
Copy link
Owner

@meblabs
Yes it's amazing what a couple hundred lines of code can produce. This style of rendering was proposed all the way back in the late 1970's and early 1980's (ray tracing and then path tracing, respectively) but computers were way too slow to even think about trying it. Hence the branch in a different direction of rasterization of triangles to the screen, which was doable, but many complicated hacks had to be introduced to get close to what you could do with a small ray tracing program (even to this day, i.e. reflection probes, cascading shadow mapping, etc..). Then along came 3d acceleration cards which helped with throwing triangles at the screen fast, and the rest is history. However, with Nvidia's recent introduction of RTX ray tracing card technology (now that computers and GPU's are fast enough in 2018), they are trying to bring back ray tracing first (you can view a couple of their presentation demos on YouTube), and then eventually real time path tracing once they get their deep-learning A.I. assisted denoisers fast enough - I have no idea how all that A.I. denoising stuff works. But yes, at its core, ray tracing is an elegant, short, simple way of rendering photo-realistic images - a window into reality!

Regarding the BVH, I have a basic triangle BVH builder that works. Typically you can survive without a BVH if you are just intersecting mathematical shapes likes spheres, cylinders, cones, boxes, etc., that's why you see everyone's beginning ray tracers rendering only those type of shapes. When you get into loading models though, it requires many triangles to be searched and intersected (because in the graphics world, most 3d models are represented as triangles), so that's when you need to introduce a BVH. I ported a C++ BVH that I found on GitHub (I gave credit to the author in the comments) to JavaScript. So it produces a list of bounding boxes and a list of raw triangles (vertex position data) in 2 different textures to be loaded on the GPU. The roadblock I was hitting was not being able to maintain a working bounding box stack on the GPU (a WebGL 1.0 limitation) so that I could search through the stack with dynamic array indexing and intersect it.

I don't know if there will be any performance difference between employing the Antimatter webgl 1.0 workaround, or just using array indexing in webgl 2.0. That remains to be seen. I'll keep you updated - I'm about to try his hack and stick it into my code and just see if it works at all. :)

@MEBoo
Copy link

MEBoo commented Sep 12, 2018

@erichlof yes I know the history of 3d graphics, I found you just after the nVidia keynote... searching "webgl raytracing"... I thought that if nVidia starts to deliver RT dedicated hardware, some mad boy could have a solution to implement it in Three.js :D ... and let's see when webgl will support the new hardware ;)
But looking to your code, is still awesome that 4/5 hundreds of code can display the reality. wow!

Ok I'll wait for good updates.. thank you!

@MEBoo
Copy link

MEBoo commented Sep 27, 2018

Hey you did it man!! 🎉🎉🎉
Awesome!

@erichlof
Copy link
Owner

erichlof commented Sep 27, 2018

Hi @meblabs and all ,

Yay, initial success! (well, for the most part anyway). Wouldn't you know it, the very day I get the WebGL 1.0 BVH shader code working is the day that three.js releases version r97, which has initial support for WebGL 2.0! Haha

So now I'm at a fork in the road. The WebGL 1.0 version works great for lower than 800-triangle models, but as soon as I tried heftier models of just a little over that, say 1000 triangles, it either will not compile, or I can see the rendered model for a brief moment (in all its glory) before the frame rate drops to 0, the browser tab crashes, and the WebGL context is lost, so you have to close and reopen the tab which is annoying.

I have a couple of ideas of why this is happening - one is all those 'if' statements inside the workaround functions for WebGL 1.0's limitation of no dynamic array indexing. GPUs do not like too many branching 'if' statements - if you throw too many at it, the shader just crashes, or won't even compile. The only glimmer of hope is that maybe I overlooked something because antimatter.js was able to load thousands of triangles with WebGL 1.0, and I am using the same workaround functions that I manually unpacked from the minified file.
The other culprit might be quality of the BVH build. As you can see from my total overhaul of the BVH builder .js file, it is pretty complex with multiple levels of recursion (definitely the most complex 300 lines of code I have ever written/ported). I printed out the tree for low poly models and it seemed to be doing a good job of recursively splitting the triangles at each juncture, all the way down until it reaches 1 triangle, which it designates as a 'leaf'. But as it scales up to thousands of triangles, who knows if it still is doing its job right. It's hard to print out 20,000 lines of data and make sense of it.

The other fork I could take is just to abandon the WebGL 1.0 workaround and go with WebGL 2.0, getting rid of all those 'if' statements in the workarounds. This sounds simple, just call WebGL 2.0 renderer from three.js setup code - but it is more involved. Since WebGL 2.0 uses OpenGL ES 3.0 (I know confusing right?) all of my established path tracing shader code on this repo will not compile right away. I have to manually go in and change stuff like 'attribute' to 'in' and 'varying' to 'in' and 'out', among other things. Here's a nice list of TODO's to get WebGL 2.0 working: WebGL 2.0 from 1.0

So once I can get WebGL 2.0 working, I can see if dynamic array indexing under WebGL 2.0 helps my crashing issue. As always I'll keep you all updated with my progress. Sorry it has been quiet around this repo the last couple of months, I have been wrestling with BVHs and WebGL 1.0 limitations and the like. :)

@MEBoo
Copy link

MEBoo commented Sep 28, 2018

ahaha... I read about the crashes... may be too many calls/recursions with 1000+ triangles?
I would consider to directly go for the WebGL 2.0 way... to simplify/optimize your BVH code.

Great work!

@erichlof
Copy link
Owner

@meblabs
I'm happy to report I successfully integrated WebGL 2.0 into my older test path tracing demo! So that means I can definitely go the WebGL 2.0 way now. I'll be making some updates to all the demos on this repo very soon. I need to manually go in and reflect the changes on each shader and the THREE.WebGLRenderer() setup code inside the init() functions for each demo. But it should work.

Yeah I don't know yet why the WebGL 1.0 version crashes after 1000 triangles. You mentioned recursion call amount, but actually no GPU shaders allow recursion of any kind, hence the stackLevel[x] approach. So you push and pop all the various branches as you descend the BVH tree which is why I needed dynamic array indexing. Now on the CPU side, it loves recursion. So that's why I went the recursion way with the Builder.js file. That uses JavaScript and is strictly CPU-side. I wish though that GPUs allowed recursion, that would make things much simpler! ;) I'll keep investigating but in the meantime I'll try the WebGL 2.0 way, which has more promise.

@EtagiBI
Copy link
Author

EtagiBI commented Jan 16, 2019

@erichlof, I'm amazed by your progress!
By the way, have you already switched to GLTF/GLB? These new formats are well optimised, so it's possible to render more complex models without any speed losses.

@erichlof
Copy link
Owner

@MEBoo
I'm about to start working on multiple models (finally, which was the title of this epic thread in the first place, LOL!), and a BVH for the BVH's after that. On the side, I have been revisiting the bi-directional scenes and seeing if there are any improvements to be made. This is because with the BVH's inside a room or house for example, most of the light sources are hidden inside cove lighting, recessed lighting panels, underneath lamp shades, etc. Even though I got the spot lights and point lights working fast with the BVH recently, those demos are just a tad idealistic so far as real world architecture and lighting plans go.

Those demos have exposed point and spot lights, and the older demos have huge spheres hanging in the air or big quad area lights (like the museum demos). Things work well in those idealistic lighting conditions, but once you try to render an apartment or bathroom with recessed lighting, the noise returns big time. The only solution to this indoors problem that I can see at the moment is bi-directional path tracing, so I am revisiting some of that old code to see if I missed any optimizations.

@erichlof
Copy link
Owner

@EtagiBI
Thank you! Yes I believe that GLTF will be the best way forward. All the GLTF models I have downloaded from places like Sketchfab, everything just works. I haven't heard about GLB yet, is that Binary? If so, I believe some of the models like the Damaged Helmet (here in the models folder of this repo) do have a binary section that describes the vertices and indices. This speeds everything up, from downloading, to loading into memory. So, if that is the case, then yes I will be using that format going forward.

@MEBoo
Copy link

MEBoo commented Jan 25, 2019

@erichlof nice new demo!!

@erichlof
Copy link
Owner

@MEBoo
Thanks! I've been busy working on moveable BVHs . I've had a breakthrough, I'm putting together a small demo to show the new functionality. Will post it soon!

@MEBoo
Copy link

MEBoo commented Jan 30, 2019

@erichlof Hey just saw the moveable BVHs with models!! Don't know how you did but it's very fast!
I see that the scene is accumulating samples where there is no movement... correct?
The result even with only 1/few samples is awesome!

So a real spotlight, low light, hi-poly model texture+other maps on a BVH updated and moved runtime!!

@erichlof
Copy link
Owner

erichlof commented Jan 30, 2019

@MEBoo
Yes I was very excited to see it actually working for the first time! The secret is that I treat the BVH like I do the boxes in the Cornell box scene. If you notice in that old demo, the mirror box and the short diffuse box are slightly turned. How I achieved this is taking advice from old ray tracing pros and instead of transforming the box and trying to trace an arbitrary rotated object (which is hard and expensive), you just transform the ray by the opposite (or inverse matrix to be exact), which puts the turned box essentially back to facing straight-on, then trace the 'non-rotated' object, which is easy to do. Then you rotate the normals and hit data back into world space with the desired rotation matrix. So on a whim, I tried this with the entire BVH, 7000+ boxes, transformed the ray by the inverse of the rotated root node of the BVH, and then trace as normal!

Now, I've been struggling with figuring out how to do this with a mesh skeleton, bones and animation, which actually move the mesh vertices in real-time on the GPU vertex shader. I thought I could go down the bone hierarchy and transform the ray by the inverse of each bone, but it turns out to be a little more complicated than that, because of weighting and skinning deformations and such. But I will post my findings if I get something working with simple animations.

About the accumulation of samples, it's actually just 1 sample over and over again, but I let the background scenery (that which is not actively moving) 'bleed' a little more from the previous frame. So there is a little more motion blur effect on the ground and walls, but it is not distracting because those things are static. 1 old sample bleeds more into the new sample, so it's like having 2 samples for a split second I guess. On the dynamic objects, or when the camera is moving, I manually turn down the 'bleeding' from the previous frame, in order to minimize distracting motion blur that would occur if I did nothing about it. It is a delicate balance between smooth motion blur which covers up distracting noise, and moving objects which you want to be more crisp and clear without too much distracting motion blur. :)

@MEBoo
Copy link

MEBoo commented Jan 30, 2019

@erichlof nice... understood!

mmm don't know why you are working on IK/animations ... it's a big world apart!
But you could check what is already done in threejs
https://threejs.org/examples/?q=skin#webgl_animation_skinning_blending

don't know if it is GPU based...

@erichlof
Copy link
Owner

@MEBoo
Yeah that's exactly what I want to have path traced inside the engine! It is in fact GPU based - the bones and animation data are stored as a GPU data texture (kind of like my BVH data texture) and then the joints' rotations and offsets are read in the vertex shader and affect the vertices of the mesh. I'm not sure how to trace all of that though, there could be as many as 200 bone matrices which are each 4x4 floats. That's a lot of inverses to do! I'm not sure if it'll work out in the end, but it's worth investigating.
In the meantime, I'm about to refactor all the demos and get rid of the duplicate code from .html file to .html file. This change will make the demo collection less error prone and easier to maintain. :-)

@MEBoo
Copy link

MEBoo commented Feb 16, 2019

@erichlof Hi!!
Any feature update other than codebase refactor?

@erichlof
Copy link
Owner

@MEBoo Hi!
I have been working on loading HDR equi-rectangular images and using those as the sky backgrounds. It's going well so far, the new GLTF model viewer #27 will benefit most from these backgrounds. Sorry it's been a little quiet lately, I had to read up on HDR images, how they work, how three.js handles them, etc. But user n2k3 and I should have a working demo soon!

I am going to try adding multiple model files to the Difficult lighting demo, the one with the slightly cracked open door and the 3 objects on the coffee table. In the original, those are supposed to be 3 Utah teapots with 1000 triangles each and different materials for each one. The current demo has ellipsoids, but I always wanted to have the 3 classic models in there, and now I have the means to add them I think. That will be step 1 to getting multiple BVH objects in. Step 2 will be a BVH for the BVH's!
:)

@erichlof
Copy link
Owner

Hi @MEBoo and @EtagiBI
Well, good news and not-so-good news - The good news is I successfully loaded multiple OBJ (now GLTFs in the new refactor) which was the original title of this now epic thread! Here's a little preview:

multipleobj

It is finally starting to look like the original classic scene by Eric Veach in his seminal paper! I realize now that I could have done some trickery with offsetting the casting rays (or how instancing is done in ray tracing) since all of the objects have the same shape, and I just might do that for the final demo - but this is actually doing it the hard way for proof of concept: it loads a teapot of 4,000 triangles, makes its BVH, uploads it to the GPU for path tracing, then loads another teapot of 4,000 triangles, makes its BVH, uploads to GPU, then loads yet another teapot of 4,000 triangles, makes its BVH, uploads to GPU. So in the end, we have 12,000+ triangles spread between 3 models, each with their own BVH and materials, as you can see in the image.

Now for the not-so-good news: If you look at the top left corner framerate, it has gone down by half. This demo used to run on my admittedly humble laptop at 50 fps, now it is at 25 fps. Still real time and interactive and amazing that all this is happening on a freakin' browser, but nonetheless not as fast as I was hoping for. It is safe to say, that adding more objects would eventually grind the shader to a halt.
Speaking of shaders, the other not-so-good news is that on first start-up compilation, it crashes my webgl context and results in a black image. I have to reload the webpage, then it usually compiles the second time (not sure why that is). This is not only annoying for me to have to keep doing every time I change something in the code and debug, but for the end user - I don't want to crash everybody's webpage, then ask them to reload a second time - just to get it to work so they can see the cool demo.

So I will continue exploring ways of first of all getting it to compile on the first time every time, and then increasing the framerate (which is less crucial, but would be nice). As always I'll keep you guys updated. I just wanted to share the initial success (tinged with a little failure, lol) and finally progress this epic thread! Sorry it has taken this long to get to this point, but other avenues I have gone down have helped get this multiple OBJs feature started and hopefully improved! :-)

@MEBoo
Copy link

MEBoo commented Feb 21, 2019

Nice news and milestone 🥇 !!!
Finally we can close this "issue" thread 😁

3 questions:

  1. is the code format indipendent? I mean... as you did before, are we able to send to GPU any THREEjs Mesh (pre-loaded with GLTF / OBJ / MyUltimateOptimizedFormat)? So are you parsing the THREEjs scene and dynamically building BVHs?

  2. About the compiler bug: I can't understand how a shader could compile a time and a time not! I've already seen something like this happen, but I simply can't understand how :)

  3. About the performance loss: are these frame drops due to multiple bvhs or to too many polygons? I mean, if you use a single BVH with 3 models inside and 4000*3 polygons, you have the same frame drop?

Afterall, I think that this is the tech of the future... but you can't dream about having a real-time real application for now. But now we can have a "background" client photo-realistic rendering engine 😉

@erichlof
Copy link
Owner

erichlof commented Feb 21, 2019

@MEBoo
Hi! About the 3 questions,

1: Well yes and no. Somewhere along the way, I think it was a couple of months ago, I decided to support .gltf and .glb (gltf in binary format for faster transmission) and remove the examples of the .OBJ files and other formats. The reason is twofold, first the .OBJ is heavier and less compressed than .glb. And second, .OBJ is an old format so even though I can extract the three.js data from the three.js created mesh when it loads, three.js does not know how to insert PBR materials into that old format, and there's no way for authors to define those types of materials in the old format when they create them in 3dsMax, Maya or Blender. GLTF on the other hand natively supports textures of all types like metalness maps, and physical materials like glass with IoR specified by the author, which I in-turn absolutely need to load into my path tracer. I know this decision might leave out some models that we have lying around, but the good news is that free websites like ClaraIO are able to convert any file type into GLTF for faster web transmission and native PBR support. In fact, you can load [insert your favorite format here] into clara, then ADD free pbr materials that are ray-tracing friendly, then save the whole thing, and hit 'Export All' gltf 2.0 and you're done. That's exactly what I did for 90% of the demo models on this repo, they were originally in another format. This decision makes my life a little easier by reducing the corner cases and codesize of handling the three.js Mesh after it has been loaded by an arbitrary unknown-in-advance format. This way I can either intercept the gltf data myself (it is in a human-readable format, the material stuff anyway) or wait further down the pipeline and get everything from three.js's correctly created Mesh with ray-tracing friendly materials and specifications (which is what I'm currently doing). Of course you could try this whole process with three.js's FBXLoader for example with some minor modifications to my demo code, but then again, I want to only think about 1 format that is built for the web, works with three.js, supports animations, and has modern detailed material specifications.

2: I ran into the 1st-time fail, 2nd-time pass compilation problem back when I created the CSG museum demos a while ago. That's why there are 4 separate demos. Initially I had all 14 CSG models in the same museum room, but it wouldn't compile at all. Then I reduced it by half to 6 or 7, then it compiled on the 2nd time only. Then I split it further into 4 demos with 3 or 4 objects each, and it compiles every time. I think it has to do with the amount of 'if' statements you have in the GPU code. CPUs love 'if' statements, GPU's - not so much! If you have too many branches, it crashes. It must not like all the 'if' ray hit bounding box on all the models - some parts of the screen have to traverse the BVHs, and some parts of the screen get lucky and hit an easily-reflected surface or wall, which also partly explains the framerate drop - GPU thread divergence.

3: Which ties into the performance drop - yes I think it is because of different models, GPU divergence and branch statements. I don't believe the triangle count has much to do with it. Take a look at the BVH_Visualizer - it handles 100,000 triangles at 60 fps on my humble machine (of course if you fly into the dragon model, the frame rate goes down, but for the most part, it doesn't even break a sweat). So there are a couple of things to try in the near future: A BVH for the BVH's (but in this simple case of 3 similar teapot objects, I'm not sure if that will help any), and like you mentioned, combine all 3 teapots into a super-teapot type shape and place a BVH around 12,000 triangles. That might work better. Also, in my last post I mentioned 'trickery' - you can actually do a modulus on the ray origin and treat it as multiple rays, and therefore it would return hits for 3 objects (like copies for free), even though you only load 1 teapot into the scene. This is a little more advanced and just a tad deceitful (ha), but something I want to try eventually - for example, a forest with thousands of trees seen from a helicopter view.

@MEBoo
Copy link

MEBoo commented Feb 21, 2019

@erichlof

  1. yes yes I know the history, it's actually written in this post! I only asked if you did the scene parser, since someone could edit materials properties run-time, and the way to do this is loading the imported mesh into THREE and then apply a material, or just another example, someone could aggregate objects/meshes to build a scene... so the best thing would be a real scene parser that will parse meshes (geometries and pbr materials), completely abstracting the objects source/format

  2. understood :/ What I don't understand, since I not checked your code, is: are the objects coded in the GPU shader? Aren't they sent to the shader from JS? So why the code was so "object" dependent in the museum demo? Here the BVH has so many "if" ?

Wow .. Hope you will find the way
Thanks for the info and the work

@erichlof
Copy link
Owner

@MEBoo

  1. Ahh ok you were meaning a pure scene parser. Yes I suppose we could do that, but the only issue is as the size and number of the models grow, it gets more error-prone for the end user to manually assign materials to selected groups of triangles inside the model. Take for instance the Damaged Helmet model in my 'Animated BVH Model' demo: Let's say that an author modeled that helmet in Maya and had no material specified (white), then saved it to .obj or whatever format, doesn't matter, then yes the user could load all 15,000 triangles and three.js would create a mesh object. Currently I am parsing the scene by extracting the child.geometry.material property from three.js, which it in turn got from the file. So, inside the GPU path tracer, it would see vec3(1,1,1) rgb white diffuse and render it as such. But if the user wants the face mask to be glass, then they want IoR of 1.5, then they want metal on the outside with a roughness of 0.1, it would be difficult to intercept the loading/creation of the three.js mesh object and manually put those in there. In fact, I don't even think you can select a group of triangles out of 15,000 say, and assign metal to triangles 2,287 to 3,013. That would be super error prone, which brings the problem further back, meaning the author would have to name the materials in Maya and assign the physical properties such as color, reflection amount, IoR in a helpful visual way inside of Maya. Then it would make sense to just dump all of that into an exported gltf file that we can read verbatim without any chance of errors or guesswork. That's how I see the problem, but maybe I'm missing something that you would want in future versions. Please let me know :)

  2. Yes if you look at the shader code for the CSG demos, there are tons of 'if' statements because of the multiple possibilities a ray could intersect a hollow, solid, additive, subtractive, or intersection overlapping pair of shapes. So as the number of objects grew in the demo room, the 'if' statements started to pile up. Now in the case of BVHs, yes there are potentially many 'if' statements for each set of bounding boxes and their triangles. But thanks to binary trees it ends up being an O(log n) search where n is the number of triangles. That works perfectly for 1 model, no matter how big, because you essentially halve the problem at each step. But if you have 2 BVHs, the right part of the screen's rays might have to go down one BVH tunnel and work on pruning it, while the left part of the screen's rays will have to prune a completely different BVH - again thread divergence rears its ugly head. And GPUs sometimes have to execute both paths of 'if' statements and then mask out the result that it didn't need in the end - super wasteful, but that's how things work I guess in GPU land. One more thing is that I've read that branches that involve possible texture lookups is generally bad practice. However, the only way to get the ray tracing on the GPU is through data textures, and searching through (or not for some parts of the screen) those big 2048x2048 textures for bounding box data. Also, if they locate an intersected triangle, they need to go to another big texture and lookup that triangle's vertex data, like UV, material, and color, etc. What I might try first is deferring the texture lookup until the last possible moment inside the bounces rendering loop and see if that helps mitigate the crashing/performance problems.

@erichlof
Copy link
Owner

erichlof commented Feb 21, 2019

@MEBoo
Oh I think i know what you mean now - you wanted to be able to change a material on the fly? Like for instance, with the helmet model, changing one of its children.geometry.material to glass instead of metal? Or blue instead of red color? If I'm understanding correctly then yes, it is possible, but the only requirement is that the user must have default materials and the materials must be assigned to the exact triangles of the original mesh. So using the helmet model again for example, in Maya they would have to say "child0: face mask, child1: metal top of helmet, child2: hoses and connections on bottom of helmet. " Then three.js would correctly assign a child.geometry.material to each of those children parts of the model (even though they might be default and all the same and boring at load time), and then the end user could say "now that the model has loaded, I want child1.geometry.material to be smoother more mirror-like metal, and child0.geometry.material.IoR = 1.4", or something to that effect. Am I understanding your functionality request correctly? If so, the only problem is that I preload the triangle data (colors, materials, uv, index of refraction, reflectivity, etc) as a 2048x2048 data texture. If the user changes something on that triangle list, I would need a way of efficiently looking up the triangles in question and then updating the floating point numbers corresponding to their options. It's not impossible, I just haven't tried intercepting it like that while the path tracer is reading that same texture every frame.

@MEBoo
Copy link

MEBoo commented Feb 24, 2019

@erichlof yes I already do this (material change) on my little project... In THREE materials / meshes / groups have names! So I can parse the scene and do whatever I want.
But not only this use case: people use THREE to compose a scene, ok pre-loading meshes from various sources, but then composing all together.
That is the why I suggest for your project to read/parse the entire THREE scene, and render it as is.
At least for the first render, then the user should be able to update the scene, and re-send changes to your shader...

@erichlof
Copy link
Owner

erichlof commented Feb 24, 2019

@MEBoo
Ok thanks for clarifying. Yes at the moment the loadModel and init functions just take the created three.scene and go through its children, saving the materials and geometry. So it is doing almost fully what you suggest. All my examples use gltf loader but as long as the user has a three.scene, that should be sufficient. In the future, just for example purposes, I might make a small demo that loads a pure three.scene in JSON format, (whatever the output is of the three.js editor that mrdoob created and maintains). That will show that the type of loader does not matter, you just need a three.scene file in the end. :-)

@n2k3
Copy link
Contributor

n2k3 commented Feb 24, 2019

That is the why I suggest for your project to read/parse the entire THREE scene, and render it as is.
At least for the first render, then the user should be able to update the scene, and re-send changes to your shader...

@MEBoo that will be the functionality of the glTF viewer I'm working on, which will be merged into this repository when it's done. Currently it loads multiple glTF models into a Three.js scene, then you can call another function that will read the scene and prepare all models for path tracing. In the near future I'll make it so that users can drag & drop new model(s) into the viewer to replace the old ones and call the same function for the new models.
Once that feature is done, you could use just the prepare function for your own scene (and not use any of the glTF loading stuff, if your models use a different file format).

@MEBoo
Copy link

MEBoo commented Feb 24, 2019

@n2k3 @erichlof
You are awesome people 😁

@erichlof
Copy link
Owner

erichlof commented Mar 1, 2019

@MEBoo @EtagiBI @n2k3

Success on multiple fronts! Not only is it compiling correctly and loading every time (without crashes), I got the frame rate up to about 30 fps, which is still real time, and I even applied a hammered metal material to the steel teapot on the left! Now it looks almost exactly like Eric Veach's original rendering for his Bi-Directional path tracing thesis. :)

multipleteapotobjects

MEBoo, I achieved the compiling every time by still loading the 3 teapots separately (so it could be any type of model, any number of models, different models from eachother, different amounts of triangles of each model, whatever you want), but then before uploading to the GPU, I merged the triangle data into one texture that still fits comfortably on a 2048x2048 three.js DataTexture. That way the shader doesn't have to read from 3 different geometry data textures (which was causing the crashing and slower frame rate), but just reads from a larger 'uber' scene data texture.

I guess it's fitting that this post is the 100th post of this epic thread! I think we can safely close out this topic. ;-D

@MEBoo
Copy link

MEBoo commented Mar 2, 2019

@erichlof congratulations! let's close the thread :)

the last question, how many vertices/polygons can handle the 2048x2048 texture?

Now...could you build a demo with a full scene of an interior space using many polygon models and many lights? Something like n2k3 showed us, but with furnitures and textures?

@erichlof
Copy link
Owner

erichlof commented Mar 3, 2019

@MEBoo
Hi! Currently I am using 7 rgba slots for each triangle. The way I figured that is: 3 vertices per triangle, times 3 x, y , and z coordinates for each vertex, that's 9. Plus 3 x, y, and z normal directions for each vertex, so that's + another 9. Then 2 u and v coordinates for textures/materials for each vertex, so that's + 6. Then pbr specs for the entire face, so stuff like MaterialType_ID, Index of Refraction, roughness, metalness, so that's another 4 values. So all together that's 9 + 9 + 6 + 4 = 28 values. Each texture slot has 4 values it can store - r,g,b,a. So the way I figure it, that's 7 texture slots times 4 possible values = 28. That's where I'm getting the total of around 7 texture slots for each complete triangle. Now a 2048 * 2048 texture has 4,194,304 rgba slots, but we have to divide that by 7 to fit all the triangle data for each triangle. So that works out to around 600,000+ faces you can have in one scene. If it has to be more than that, then we can bump up the texture size to 4096x4096, which gives us 16,777,216 slots for a grand total of (divided by 7 again) = just shy of 2,400,000 faces. The reason I currently have 2048x2048 textures in the demos is because I had initially thought that I was going to be able to load the models on mobile and not all mobile platforms support those huge 4096 textures. But even the simple BVH demos don't work on my Samsung Galaxy 7 anyway (maybe they do on a Galaxy 9, I don't know), so in the future we can just bump up the textures to 4096 and leave mobile behind (just for those type of heavy BVH demos and projects).

About the room demo, yes that would be the ultimate if we could have any number of lights and a lot of triangles in the scene at the same time. n2k3 is defintiley pushing it forward in the right direction, his awesome apartment model has 100,000+ triangles and a cool loading animation. Let me merge his project and then maybe we can work towards that by adding numbers of lights. After adding all that, it will probably only run at 10 fps in the browser, but hopefully it will run, compile every time, and at least be somewhat interactive. :)

@MEBoo
Copy link

MEBoo commented Mar 3, 2019

@erichlof good & cool!!

Maybe will run at 10fps today... but hey this project is for the future ;)
And 10fps with which video card? I have a 1080ti to try ... let me try :D

@erichlof
Copy link
Owner

erichlof commented Mar 4, 2019

@MEBoo
Just curious - what framerate do you get on the Difficult light demo above with the 3 teapots added in now? I have a Toshiba laptop with integrated Intel graphics that gets 29-30 fps but I was wondering what you would get with a dedicated graphics card?

I'm closing out this issue now, but you can still reply to it if you like. :D

Thanks to all involved!

@erichlof erichlof closed this as completed Mar 4, 2019
@MEBoo
Copy link

MEBoo commented Mar 7, 2019

@MEBoo I'm here! Couldn't test these days :(
60 fps ... maybe more but webgl is capped ;)
I get 60 fps also on the new GLtf viewer demo (even with pixelRatio = 1 on a 2560x1440p monitor, don't know if resolution is correlated to fps)

The only way to drop fps is to go into the space in photo photo

@erichlof
Copy link
Owner

erichlof commented Mar 7, 2019

@MEBoo
Wow that's fantastic! I had no idea the amount of speed up a dedicated graphics card could give! On my humble laptop with Intel integrated graphics I was getting 20 to 30 fps inside the house with pixel ratio even lowered to 0.5. If I increased it to 1.0, it would maybe achieve 7 or 8 fps, lol.

Well it's comforting to know that users with better systems will achieve real time results heading toward 60 fps, rendering 100,000 plus triangles, all inside a browser!

That's also a nice confirmation and testament to the BVH builder and transversal code that was inspired by previous authors and custom fit for this project.

Thank you for posting the results! :-D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants