erichlof / THREE.js-PathTracing-Renderer

Real-time PathTracing with global illumination and progressive rendering, all on top of the Three.js WebGL framework. Click here for Live Demo: https://erichlof.github.io/THREE.js-PathTracing-Renderer/Geometry_Showcase.html
Creative Commons Zero v1.0 Universal
1.91k stars 177 forks source link

Canvas as texture #34

Open VinAr22 opened 5 years ago

VinAr22 commented 5 years ago

Hi! Great project!!! Is there way to use canvas as texture?

erichlof commented 5 years ago

Hello @VinAr22 Thank you! Yes it should be possible to use an html canvas element as a texture. Each demo (the .html file) has a fragment shader (.glsl) associated with it of the same name (the heart of the path-traced rendering) and an associated JavaScript file of the same name that loads in any images that are necessary and creates the uniforms (links to the associated fragment shader).

If you look at BilliardTable.js for instance, you can see how the textures (such as cloth and wood) are first loaded using the three.js library and then handed over to the shader via texture uniforms. Once the fragment shader knows about them, it can use the uniform for each texture inside the pathtracing loop and make that the default diffuse color lookup for that surface or object. In order to use the textures in rendering, you must provide uv coordinates when you call the texture(uniform, uv) function inside glsl - the uv's in ray tracing are traditionally corresponding to where the ray strikes the 2d surface, XY or XZ plane. A good surface to get started with is a rectangle or plane because the uv texture lookup can be easily found or manually given. Again you can see how I handled different uv's in the BilliardTable_Fragment.glsl file (where the function texture() is called). The pow(,2.2) stuff is just gamma correction, but may or may not be necessary in your canvas case. UV's for texture lookups are tricky - I have only really mastered how to use them on planes, rectangles, and spheres. To see a textured sphere and how to get the uv's, refer to my Compleat Angler classic demo.

Getting back to using a canvas instead of a .png or .jpg, I would assume that if you can just load it in with the three.js library, you would then just pass it to the fragment shader via the uniform in the same exact way that you would a .jpg image - they're all just 2d image data. In other words, the path tracing fragment shader doesn't care how you obtained the image, it just needs access to it via a texture uniform.

Here's a link and its source code for an example of how three.js loads in and uses a canvas element as a surface texture. Once you have the material.map populated, just pass it to the fragment shader through a dedicated uniform and it should work.

Let me know if you run into any problems, I will try to help as much as I can. Best of luck! -Erich

vinkovsky commented 3 years ago

Hi @erichlof! Thanks a lot for your reply, I have lost access to my account and have not seen your wonderful explanation yet. Thank you for your work