Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Using Normal Maps with Custom Lit Shader and 2D lights

Discussion in '2D' started by Dragoniff, Jul 5, 2023.

  1. Dragoniff

    Dragoniff

    Joined:
    Jan 31, 2021
    Posts:
    1
    Hello people, I'm messing around a bit with making custom lit 2d shaders with shader graph by grabing the 2d light texture with the light texture node.
    I'd like make my shader work with normal maps, how do I do that?
    I already got a normal map secondary texture in my sprite, everything works fine with the default lit shader, If someone could show me how to do the exact same effect with a custom shader, I can figure the rest by my own.
     
  2. venediklee

    venediklee

    Joined:
    Jul 24, 2017
    Posts:
    143
    You just sample the normal map and attach it to the normal in the fragment shader.

    Some notes:
    1- normal map field's reference must be _NormalMap (if you name the field NormalMap, it'll be referenced as _NormalMap)
    2- normal map sampling must be type Normal, space Tangent for accurate results
    3- main sprite must have its normal map assigned as a secondary texture with name _NormalMap or you must assign a normal map manually to the material
    4- if you dont have the normal in the Fragment block, right click on it -> add block node -> normal


    ps: the normal map field in the example image has White mode instead of NormalMap mode, but idk if it effects anything given the type of normal texture is set to normalmap. You should set its mode to normal map anyways!
    upload_2023-7-6_1-57-52.png
    upload_2023-7-6_1-59-56.png
     
    Last edited: Jul 6, 2023
    MaxwellTan likes this.
  3. venediklee

    venediklee

    Joined:
    Jul 24, 2017
    Posts:
    143
    Correction:

    Recently I wanted to use custom lit shader with normal maps as you described
    and realized 2d custom lit doesn't automatically work with normal maps. I thought I should update this thread since this was a top result in my google search.

    The solution to make 2d custom lit work with normal maps is by sampling the _LightTexture_1_0*, _LightTexture_1_1*, _LightTexture_1_2*, _LightTexture_1_3* and applying the blend modes manually. Note that each light texture1 corresponds to each blend mode in your 2d renderer settings upload_2023-8-7_1-11-51.png

    So, for example if you only have 2d lights with multiply blend mode(_0), you can use this shader to apply the normal mapping like the sprite-default-lit shader:
    upload_2023-8-7_1-22-41.png

    If you have lights with different blending modes, you'll have to combine the results, that is up to you to implement

    *_LightTexture_1_X may not be the actual light texture you want to sample, check the frame debugger to see which light textures are the ones you should sample. For example, if you don't have any shadow caster2d's in your scene, you'll probably want to sample _LightTexture_0_X. Disable almost everything in the scene to make things easier to debug in the frame debugger. I realize this can be a bit finnicky but it is better than writing a full renderer

    Apologies for the mis-answer in the first reply!!
     
    MaxwellTan likes this.
  4. anilsayar

    anilsayar

    Joined:
    Oct 14, 2018
    Posts:
    14
    Hello,

    I am trying to apply normal map and take advantage of light effects in my 2d game. But, it doesn't seem to make any difference. I am not an expert in this area, please bear with me. Here is what I did:
    - I found an image online, and extracted its normal map using GIMP.
    - I added them to Assets Folder. I changed textures type of Image to Sprite (2D and UI) and normal map to Normal map. - Inside the image's sprite editor, I added my normal map as _NormalMap under Secondary Textures. I also added image and normal map to the materials I created (I am confused here). One of them uses default Universal Pipeline - I just set the diffuse and normal map. Other one is 2D lit sprite shader graph that I created. I set its Base Color and Normal nodes exactly as you did above. Sample Texture 2D node, linked to Base color has type set to Default, other Sample Texture 2D node, linked to Normal has type set to Normal. Both nodes' spaces are Tangent. I set the name of normal as _NormalMap both in shader graph and Secondary Textures inside Sprite Editor.

    After all, I am playing with lights, turning on & off image's normal map. I see zero difference. I am testing the normal map effect with different 2d lights, turning on & off their Normal Map rendering feature. Zero difference...

    Aside from my question above, I also would like to add texture animations to my sprites. To clarify my terminology: Sprites are the small images that are extracted from an image (sprite sheet). I realized that in the Shader Graph (I use 2D lit sprite), you cannot add those sprites. Instead, you must add the whole sprite sheet as Texture to the shader graph, then exract the sprites inside there - just like you do inside Sprite Renderer. I would like to know if I am missing something at this point. Because there is a dimensional difference between sprite sheet and small sprites, there will always be transparent gaps around the sprite shown below. I don't want that.

    I am sorry, if this topic is diversified too much. But, these are the ones that I am dealing with. Thank you!

    upload_2023-8-13_11-17-14.png
     
  5. venediklee

    venediklee

    Joined:
    Jul 24, 2017
    Posts:
    143
    In the future please create a new thread instead. It looks like your questions are mostly not related to using normal mapping in custom lit shaders. You can add a link to other threads when creating your threads for clarity etc.

    It is also good practice to create multiple threads instead of a large one containing multiple questions.

    You don't have to do it, secondary texture references are automatically set by Unity. So, for a shader you can directly use the secondary texture references without assigning them. It will look empty when you select a material, it is not empty in reality

    You should not be using these stuff if your shader is "sprite lit". Only use this stuff if your shader is "sprite custom lit".
    upload_2023-8-13_11-57-3.png

    I can't really tell what the problem is, even the image you posted doesn't mean anything. Maybe your normal maps you
    is wrong; maybe your urp asset is not assigned in the graphics settings; maybe your lights are too far away from your sprites(including the Z distance); maybe your lights are not effecting the layers of those sprites; idk, there is so much that can go wrong.

    1. Create your sprite sheets as usual
    2. Create your secondary texture that is as large as the main texture. The normals should align with main texture. Don't forget to assign the main texture's secondary texture
    3. Slice your sprite sheet if it is not already sliced
    4. Use one of the sprites as the initial sprite of a sprite renderer
    5. Change the sprite renderer's sprite with the next sprite in the sprite sheet
    Instead of 4 and 5, you can select multiple sprites and drag&drop them on to the scene; Unity will create an animation automatically for you. If you select the first sprite on a sprite sheet and shift click the last sprite, then drag it onto the scene, the entire sprite sheet will be animated etc.

    If you have any other questions please create a new thread. If you were actually trying to use normal maps with custom lit shader, please explain yourself better(images help a lot - you can just post your shader graph instead of describing it etc.)
     
    MaxwellTan likes this.
  6. anilsayar

    anilsayar

    Joined:
    Oct 14, 2018
    Posts:
    14
    I appreciate for your reply. Let's continue from normal maps. I see that is little complicated to discuss this problem here. I am now adding some photos, I hope that they help you understand the problem. Let's start with a very basic Shader Graph. I only set texture and normal just to see whether Secondary Texture in Sprite Editor is working properly (or does it make a difference). I changed it to custom lit, as you mentioned above. This doesn't look like a good idea, as it completely enlightens the image with no dark sides. (see pic 3) shader graph custom lit.png

    Here the normal map looks navy blue - but inside the Assets Folder, it looks like the second photo (looks like a problem to me)
    Normal Map.png

    Currently, the global 2d is off in the scene. I set up this texture with material on it, plus add a freeform light with its Normal Map set to on & off. During runtime, here is the result of above shader with custom lit set (light so-called renders normal maps): As you can see, the light cannot do its job here. light + texture, normal render on.png

    They were the results taken when the shader is "sprite custom lit". When I change it to "sprite lit", as usual, the followings results are taken. They look fancy this time, but same results are taken when I completely remove normal map from the image. So, there is still no impact of normal maps.
    normal map render off + sprite lit shader.png
    normal map render on + sprite lit shader.png
     
  7. venediklee

    venediklee

    Joined:
    Jul 24, 2017
    Posts:
    143
    Perhaps you misunderstood the purpose of sprite custom lit. If you want regular light interaction with normal maps just use sprite lit. You'll only need to use sprite custom lit when you need a *very* special interaction between light & normal maps.
    It is not a problem, that is how it is supposed to look(I don't exactly know why, might be because sampling a normal map unpacks it etc.)

    I don't know how freeform/sprite lights behave because I don't use them. I remember one of them having trouble lighting when it falls in the negative world coordinates etc.

    Spot lights work fine. If the normal distance is 3, odds are it'll feel like there is no normal mapping. 2D Normal distance is used by the light for the Z distance to the sprites. If it is too low(like 0.01) it'll look like it is lighting a smaller area than it is supposed to, if it is too high, it'll feel like it is not normal mapping at all.

    Here is an isometric cube and its normal map for 2d lighting. Try using 2d lights on it with the default sprite lit material. cubetest.png cubetest_normal.png
    this is how it should look with the default sprite lit material:
    upload_2023-8-13_20-38-4.png

    One final recommendation: "generating" normal maps from main textures will definitely not give the best results. You can check out ambientcg, polyhaven and textures .com sites etc. for proper normal maps. Check their licenses!

    Also, please, create a new thread. Your question is about using normal maps with 2d lights; this thread is about applying normal maps to custom 2d lit shaders. You can ask anything I missed in a new thread. Feel free to tag me in that thread.
     
    MaxwellTan and anilsayar like this.