Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Normal Map lighting effects with image sheets
Started by andrei18 May 09 2018 04:28 AM

11 replies to this topic
[TOPIC CONTROLS]
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

andrei18

[GLOBAL: userInfoPane.html]
andrei18
  • Observer

  • 18 posts
  • Corona SDK

To follow up on another (now closed) topic normal-map-filters-help-needed, I have new observations on the matter:

 

In the below image, the top row has individually loaded images, the second row - frames from an image sheet (2 images, sheet size 512x256). It is clear that point light position in texture space (0 to 1) is applied to the whole sheet texture, not the used frame. As I read in other posts, it has to do with OpenGL design / limitation.

 

Is my assumption correct that it is not possible to use image sheets with normal maps for lighting effects and I should stop wasting time trying?

 

Attached File  normal_map_g34sfg.gif   595.47KB   1 downloads

 

Second question is when I use directional light with the same settings as above, I get a weird "flip" effect, when the light seem to roll over the center of the image at the end of the loop.

 

Attached File  normal_map_df2343fg.gif   367.55KB   0 downloads

 

However, when I comment out the following code (effectively disabling normalization of the coordinate values to 0--1 range from original -1.414 -- 1.414 range), the light animation looks correct:

--	posX = Remap(posX, -1,1,0,1)
--	posY = Remap(posY, -1,1,0,1)

Attached File  normal_map_aaer34.gif   310.24KB   0 downloads

 

This makes me think that this statement from the docs is false :

"The origin and the growth direction of each axis is the same as described for pointLightPos"

 

and, in fact, dirLightDirection origin is at the center of the image, as opposed to top left corner.

 

I'd appreciate if anyone can shed some light on this for me (no pun intended)

 

Here is the function I use to calculate light position:

	-- LIGHT TIMER FUNCTION
-- calculate rotation
	local lightTimer = timer.performWithDelay( 100, function() -- inline function repeats 10x/sec
            
    for i = 1, #testPlates do
      
		local testPlate = testPlates[i]
--      testPlate.rotation = testPlate.rotation + 4     	
--	local rot = math.mod(testPlate.rotation,360)
	local rot = system.getTimer() / 10
		
	local rotrad = math.rad(rot)
	
	-- normalizaton 
	local Remap  = function(value, from1, to1, from2,  to2) 
		return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
	 end
	
    -- how far is light from the center
	local origX = 1
	local origY = 1
	
	-- standard rotation formula
	local posX = origY * math.sin(rotrad) + origX * math.cos(rotrad)
	local posY = origY * math.cos(rotrad) - origX * math.sin(rotrad)
	
        
        print("posX:"..posX)
        
--	posX = Remap(posX, -1,1,0,1)
--	posY = Remap(posY, -1,1,0,1)


	testPlate.fill.effect.dirLightDirection  = { posX, posY, .1} -- x, y, z values for the Normal Map ; applied to each object
--	testPlate.fill.effect.pointLightPos  = { posX, posY, .2 } -- x, y, z values for the Normal Map ; applied to each object
end 
-- end for loop

end, 0)    -- end inline function and set repeat to infinite
	
-- LIGHT TIMER FUNCTION END

The test project is attached as well.

Attached Files



[TOPIC: post.html]
#2

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,648 posts
  • Enterprise

Hi @andrei18.

 

Thanks for the report. I'd love to get Engineering to investigate this, but they are working on critical, time sensitive issues at the moment. I think your best bet, since you have a sample project is to use the "Report a Bug" link at the top of the page. 

 

But before you do, could your Remap function be generating divide by 0 issues? I would think that would generate a runtime error, but it's possible to disable them.

 

Rob



[TOPIC: post.html]
#3

sporkfin

[GLOBAL: userInfoPane.html]
sporkfin
  • Contributor

  • 489 posts
  • Corona SDK

@andrei18  Correct, image sheets cannot be used with composite effects.  There is an open request for that on the Corona feature request site, please add your vote



[TOPIC: post.html]
#4

andrei18

[GLOBAL: userInfoPane.html]
andrei18
  • Observer

  • 18 posts
  • Corona SDK

@Rob: Interesting note on division by 0, I got that code from the web and didn't really study it. Just ran some tests to simulate this - with from1 and to1 being equal , no errors - getting -1.#INF as the result. But surely, there is no real life case where source range will be 0 length, right?

 

When you suggested to file a bug report, you meant the first or the second issue I described? the first being paint effect looking at the whole image sheet texture, the second - directional light coords.

 

@sporkfin: Thanks for providing a closure for me :( . I did add my vote to the request.



[TOPIC: post.html]
#5

horacebury

[GLOBAL: userInfoPane.html]
horacebury
  • Corona Geek

  • 3,069 posts
  • Corona SDK

Probably won't help, but I got around this issue by scaling a fill of a rect to show only the frame I want, instead of using the image as a sheet. The FX then apply just fine.



[TOPIC: post.html]
#6

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,648 posts
  • Enterprise

I was thinking the bug report would be for the 1st issue since it needs some research. But it might not hurt to submit the 2nd one as well.

 

I tried tracing through you Remap function and I can't see how it would generate a div by zero error, but that certainly feels like what's going on.

 

Rob



[TOPIC: post.html]
#7

sporkfin

[GLOBAL: userInfoPane.html]
sporkfin
  • Contributor

  • 489 posts
  • Corona SDK

@horacebury  That's a cool workaround.  I'll have to give it try.  It would really cut down on my texture load!



[TOPIC: post.html]
#8

StarCrunch

[GLOBAL: userInfoPane.html]
StarCrunch
  • Contributor

  • 803 posts
  • Corona SDK

@andrei18 A direction doesn't have an origin. It's a vector, a difference of two points. As the docs say, the principal directions (horizontal, vertical, away/toward the screen) are the same as with points, which are basically the origin plus a direction.

 

What might be useful is a note such as "The natural way to calculate the direction is by subtracting the point {.5, .5, 0} from pointLightPos."

 

On the GPU side of things you have texture coordinates typically in the 0-1 range, rather than pixels as with image sheets. These are provided to your shader, and it's pretty easy to do a remap like your own and turn them back into vectors and so on.

 

With an image sheet, though, you suddenly can't rely on this nice 0-1 zone, and somehow the effect needs to know what you actually have. The way I've achieved this in some of my own effects is by supplying the center and dimensions of the object in question (either actual position / size or, more robust but less flexible, the texture region) and remap from there. Unfortunately this costs you those shader inputs (assuming you have any to spare!) and the trouble that goes with it. I imagine concerns like this are why the various effects don't support it.

 

Can you use snapshots or canvases?



[TOPIC: post.html]
#9

andrei18

[GLOBAL: userInfoPane.html]
andrei18
  • Observer

  • 18 posts
  • Corona SDK

@StarCrunch: Wow, thanks for this in-depth explanation, I'll have to take some time to digest it.

I am not sure I want to go down the snapshot or canvases route, since I can do away with a series of individual images.

 

Would using snapshots/canvases have advantage performance-wise over single images?

 

@Rob: with all this info, it doesn't seem like a bug, besides, this has been brought up multiple times in the past on this forum and is mentioned in docs under limitations in compositePainit section, so I will hold off with a bug report submission.

 

On a side note, I was experimenting a bit and added filename parameter to fill options like:

type = "composite",
     paint1 = {type = "image",    sheet = imageSheetColor,  frame = 2, filename="texture.png"},
     paint2 = {type = "image",    sheet = imageSheetNormal,  frame = 2}
     }

The fill effectively reads the dimensions from image specified in by filename parameter, but loads texture from image sheet. It didn't help since it just scaled down my image sheet on x to fit, but I thought I'd share. Maybe someone can use this for an alternative scaling method or some other workaround.

 

Attached File  normal_map_Ere6345.gif   573.44KB   0 downloads



[TOPIC: post.html]
#10

sporkfin

[GLOBAL: userInfoPane.html]
sporkfin
  • Contributor

  • 489 posts
  • Corona SDK

@andei18  I'm curious, what are the dimensions of the full image sheet and each frame?



[TOPIC: post.html]
#11

andrei18

[GLOBAL: userInfoPane.html]
andrei18
  • Observer

  • 18 posts
  • Corona SDK

@sporkfin: frame 256x256 sheet 512x256 (2 frames - horizontal)



[TOPIC: post.html]
#12

sporkfin

[GLOBAL: userInfoPane.html]
sporkfin
  • Contributor

  • 489 posts
  • Corona SDK

Can you try running it again on a 512x512 sheet (4 frames)?




[topic_controls]
[/topic_controls]