some notes about texels lighting shading ( "lightmapping" "shadowmapping" )

Started by RemiD, October 01, 2019, 22:23:07

Previous topic - Next topic

RemiD

hi,

some notes about texels lighting shading ( "lightmapping" "shadowmapping" ) :

so i am trying to create my own texels lighting shading system, so while i learn and experiment, i am going to post some notes, for those who are interested in this...
i will (try to) keep it simple to make it understandable ok ? :)

a mesh has one or several surfaces,
in a surface there are vertices and triangles
each vertex has a position, and a normal (vector pointing outwards), and UV coordinates
each triangle has 3 vertices
you can color a surface in different ways, here we will use the texels (of a texture)

a texel area (a part of the texture) can be applied on a surface area (a part of the surface, on the triangles) by defining what we call UVs
U,V are values between 0.0 and 1.0 representing the x,y position of a vertex on a texture
example :
we have a square made of 4 vertices, 2 triangles, with :
vertex0 position = -0.5x, 0.0y, +0.5z
vertex1 position = +0.5x, 0.0y, +0.5z
vertex2 position = -0.5x, 0.0y, -0.5z
vertex3 position = +0.5x, 0.0y, -0.5z
so the size of the square is 1.0x1.0unit (1.0width 0.0height 1.0depth)

for the colors, we have a texture of 128x128 texels
the colors area is only 100x100texels from 0x0y to 99x99y
we want to color the square with the colors area, vertex0 at top left, vertex1 at top right, vertex2 at bottom left, vertex3 at bottom right (of the colors area)
let's calculate the UVs (for coordset 0) :
V0U = 0.0/128 | V0V = 0.0/128
V1U = 100.0/128 | V1V = 0.0/128
V2U = 0.0/128 | V2V = 100.0/128
V3U = 100.0/128 | V3V = 100.0/128

why 100.0/128 and not 99.0/128, you may ask ? because UV is the position of a vertex on the texture, not of a texel.
so the vertices must be around the 100x100 texels area...

easy enough ? ok let's complicate a little bit ;)

so we can now apply a texture on a surface, good (you don't need to do that in code, there are tools to help you (like Fragmotion), but it can be useful to understand what it is and how it works.)

but in Blitz3d (and others 3d engines) there are 2 UVs coordsets, why ?
VertexTexCoords(surface,vertexindex,U,V,W,coordset) (disregard the "W", not used in Blitz3d)
TextureCoords(texture,coordset)

well usually the UVs coordset 0 is used to apply colors on a surface (="diffusemap") and the UVs coordset 1 is used to apply lighting shading (using texels) on a surface (="lightmap" or "shadowmap")

now what can be confusing, is that, the shape is the exact same, the structure is the same (vertices and triangles), but the UVs of the coordset 0 and the UVs of the coordset 1 can be (and usually are) different, why ?

well, the first reason is because you use tools and you have no idea what you are doing, and the exporter is often buggy, so at the end it is quite messy...  :P

to be serious, usually we need more details (so a smaller texel size, so more texels in the texture) when coloring the surface, and we don't need as much details (so a bigger texel size, so less texels in the texture) when lighting shading the surface.
example :
previously we had a square which measured 1.0x1.0unit (1.0width 0.0height 1.0depth)
and we applied a colors area of 100x100texels
so in this case the texel size will be approximately 0.01u (=1.0/100)

now for lighting / shading using texels (="lightmaping" / "shadowmapping"), we don't need as much details, so we could a texel size of 0.1u
so for a square of 1.0x1.0, we would only need a 10x10texels area.

but it would be nice enough for lighting / shading and shadows, and also faster to calculate how each texel must be lighted shaded (colored with lightsource color, considering the distance lightsource->texel, and considering the angle between lightvector and texelnormal)

for the lighting shading, we have a texture of 16x16 texels
the lighting shading area is only 10x10texels from 0x0y to 9x9y
let's calculate the UVs (for coordset 1) :
V0U = 0.0/16 | V0V = 0.0/16
V1U = 10.0/16 | V1V = 0.0/16
V2U = 0.0/16 | V2V = 10.0/16
V3U = 10.0/16 | V3V = 10.0/16

easy enough ?

take a look at a demonstration, in code :
https://www.syntaxbomb.com/index.php/topic,6298.0.html

RemiD

ok, now, let's talk about how to do the texels lighting shading (="lightmapping")

well, as we have seen before, you have a shape, you have a colors (="diffuse") texture, you do the UVmapping of coordset0 in your favorite modeling editor. (Fragmotion!)

now, for the lighting/shading texture, and for the UVmapping of coordset1, i see 2 approaches :

approach 1 : either you use a lightmapper (like mapplet or giles or 3d world studio or similar), where you position/rotate your shapes, then position your lightsources, define their intensities/falloffs/colors, define the texel size (rarely possible), and the lightmapper will automatically UVmap your shapes, and calculate the lighting/shading using its own formula.

the pros : easy to do (depending on the interface), fast to UVmap, fast to light/shade the texels

the cons : not compatible with your map editor or your game, difficulty to position / rotate shapes, difficulty to scale the map, can't define a uniform texel size, sometimes ugly lighting/shading formula, bugs/artifacts which can't be corrected since you can't modify the procedure, errors when exporting.

approach 2 : you UVmap your shapes for lighting/shading in your favorite modeling editor too (with a different texel size than your colors texture), and then calculate the lighting/shading of texels using your own formula

the pros : easy to do (but require a good understanding of your modeling tool and of your 2d/3d engine), you can make it compatible with your map editor and your game, no problem to position or scale, you can choose the texel size, you can customize your lighting/shading formula and fix the artifacs/bugs, no problem with exporters.

the cons : it takes more time to UVmap each shape for lighting/shading rather than having a tool doing it automatically, but in the end, you don't have to try hundred times to get the result that you want... you need a good understanding of 3d things like surfaces, vertices, triangles, textures, texels, uvs, 3dvectors, 3ddistance, 3dangles, to make your own lighting/shading formula...

however i have not found a way, in my modeling editor (Fragmotion) to define for the same shape, 2 different UVs, one for coordset0 (for colors), and one for coordset1 (for lighting/shading of texels), and i am not sure if this option exists in others modeling editors... so what i did was to model the shape once, but then UVMap it and export it twice (one for colors (texel size = 0.01u) with UVs for coordset0, one for lighting/shading (texel size = 0.1u) with UVs for coordset1), then using a procedure, merge the 2 meshes in 1 mesh with the 2 Uvs coordsets...

it works! 8)

RemiD

so, as i said, i am trying to create my own texels lighting / shading system (lightmapping) but to keep it simple, i decided to make my maps with premade parts which are already UVmapped for colors and for lighting / shading.
so the remaining things that i have coded these pasts days are :
->a way to identify which texels needs to be lighted / shaded (not all texels on a lightmap need to be considered...)
->a way to get the texel properties, like texture 2D position (TX,TY), world 3D position (WX,WY,WZ), world 3d normal (NX,NY,NZ) (same as the triangle normal)
->save these texels properties in a file
->load these texels properties from a file

the method to identify which texels belong to which triangles was quite tricky (some texels are not fully inside a triangle), i had to use 2 workarounds... but it seems to work well now...

and now i am working on the lighting/shading method / formula, and it will be similar to the lighting/shading method / formula that i have already coded for vertices lighting/shading, that is :
->distance attenuation (depending on distance between lightsource and (center of) texel)
->angle attenuation (depending on angle between normalised vector of light->texel and normal of texel)
but this time i will also consider the obstacles, to project shadows (i plan to use linepicks)

first experiment with distance attenuation :
http://rd-stuff.fr/blitz3d/screenie-texels-lighting-shading-distanceattenuation-20191006-1806.png

second experiment with distance attenuation + angle attenuation :
http://rd-stuff.fr/blitz3d/screenie-texels-lighting-shading-distanceattenuation-angleattenuation-20191006-1811.png

third experiment with distance attenuation + angle attenuation + casters and projected shadows :
http://rd-stuff.fr/blitz3d/screenie-texels-lighting-shading-distanceattenuation-angleattenuation-casters-20191006-1842.png
well there are some weird artifacts but it works 8)


so after some more testing, i realize that :
->real time texels lighting shading is fast enough as long as each shape is quite small and the texel density is not too high (ok for small areas of 3*3*3 or 5*3*5 or similar, with a texel size of 0.1unit max),and as long as it only takes into account the distance attenuation and the angle attenuation, but not casters ! or it becomes too slow to calculate if each texel can be reach or not by the light...

->precalculated texels lighting shading (=lightmapping) can be done in the way i followed here (with preuvmapped, pretextured shapes for the lighting shading layer, with a (approximately) uniform texel size)


anyway, not sure what i will do with this !