Ni fait ni à faire

Creating light map texture of the surface of a uv-mapped mesh, in real-time

Recommended Posts

Hello !


I'm working on a project in which a moving light revolves closely around an arbitrary model, revealing the surface it has lit, in a "fog of war" style (but with precise lighting):



(this model is "Ice Asteroid" by jesterelly and is under CC-By license)

(the *point* light is just an example, may as well be directional light with a shadowgenerator).


To do this, I must keep track of once-lit areas to display them even if they are not illuminated atm. As this information can only be assigned to the whole surface (the camera is mobile, and all surface is concerned), I thought of using a texture to store it, "inside" the model material.


I was kindly pointed toward RenderTargetTextures, which seem the way to go :) , but I struggle with implementing my plan (and I don't know if it is correct anymore) :


1) using a new material = standard material + a light map texture, which stores all pixels of the diffuse texture ever lit ( 0/1 states), and display (or not) a fragment accordingly. Seems OK.


2) the "light map" is a RTT which

  • onBeforeRender replaces the model material with a "detect light" custom material : its fragment shader output only convoys light/shadow information, and it is displayed on a plane, to form the model UV map (but only with lit/unlit zones).
  • the rendering takes place, creating the "instant" light map
  • onAfterRender puts back the almost-standard model material, and makes an "addition" of the newly created light map and the previous one (final_uvpixel_value = uvpixel_value_1 + uvpixel_value_2),  passing it as a texture to the model material.



I scratch my head on these 2 points : in particular, I have no idea how to access to the "light state" of the model surface, presented as a flat texture. I tried to "unwrap" my model by replacing

gl_Position = viewProjection * finalWorld * vec4(position, 1.0);


gl_Position = vec4(vDiffuseUV,0., 1.0);

in the standard material vertex, but so far I only got beautiful glitches (always on UV-mapped models). I can't think of another way to go for the moment.


Any idea about this "real-time surface illumination texture" is welcome :) (thank you very much for reading this)

Share this post

Link to post
Share on other sites

Hey again :)


OK, I've found a solution that works in theory, although it might be slow & not look incredibly good.

I've put in green the steps that should be done with shaders, and in blue the steps to be done with JS code.


1/ create a new square texture for your object, containing for each pixel its coordinates like so: Red = U (0 to 1), Green = V (0 to 1), Blue = 0 (important for later)

Note: this texture can (and should) be of lower resolution than the true one, in order to gain performance


2/ before drawing the final render of your object, render it first with this "coordinates" texture from the light perspective, in a separate RTT, and without shading


3/ initialize an array of texels defined by their (u,v) coordinates; this will be the list of texels you'll need to mark as "already seen"


4/ scan every pixels of the separate RTT, and for each:

  a. if its 'Blue' value is >0, skip

  b. otherwise, obtain the coordinates from the pixel 'Red' and 'Green' values (cf. how this texture was built)

  c. check if you have a texel with these coordinates in your array; if not, push the texel in it


5/ go through all the texels you've collected in your array; for each of them, modify the 'coordinates' texture by setting the 'Blue' value to 1 at their coordinates


6/ when you do the proper rendering of your object, check for each pixel rendered its corresponding color in the 'coordinates' texture; if the 'Blue' value is zero, it means it has never been lit and you should skip it.


I found the "texture containing UV info" method while browsing forums and I must say it sounds like a very good start for you! Hope you eventually make it out.

Share this post

Link to post
Share on other sites

Hi again !


This seems to be a working solution (which is an incredible leap forward :D thx so much), but the resolution ( 256x256 texture) and performance constraints are difficult trade-offs. I can't believe there is no way to do this in a more WebGL way, I keep searching & keep this thread updated.


Big thanks :)

Share this post

Link to post
Share on other sites

gl_Position = viewProjection * finalWorld * vec4(position, 1.0);


gl_Position = vec4(vDiffuseUV,0., 1.0);

in the standard material vertex



I managed to get the "flattened light map" effect by patching the Create Your Own Shader Phong vertex shader in a better way :

vec4 outPosition = worldViewProjection * vec4(uv.x, uv.y, 0.0, 1.0);gl_Position = outPosition;



(flattened surface of a lit sphere)



It still needs some tweaking ( specular looks strange) but is definitely what I was searching for. Big thanks to jahow !

Share this post

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.