#Texel based shading lighting

1 messages · Page 1 of 1 (latest)

vocal delta
#

Hi. I'm using urp. Making a 2.5d pixel art texture 3d objects
Is there a way for objects to be lit but by it's texture pixels, instead of screen pixels?

This asset seems to be it but I'm not convinced.. and seems to only be for shadows, not light attenuation?
https://assetstore.unity.com/packages/vfx/shaders/3d-pixel-art-shadows-texel-space-lighting-shader-for-urp-170074

There's also https://github.com/NullTale/LutLight2D
But this is only for 2d rendering. Unity 6's 2d light for 3d is also not the solution to make this work for 3d mesh

There's also propixelizer, but this is a pixel art filter and kinda not what we wanna achieve

So.. yea. And ideas?
I hope this can be achieved with just node stuff in shadergraph. Or.. some available asset or open source thing. (I'm not a graphics expert..)
Hopefully..
Cheers!

Add depth to your next project with 3D Pixel Art Shadows (Texel Space Lighting Shader for URP) from Ciberman. Find this & more VFX Shaders on the Unity Asset Store.

GitHub

⚪ Stylized 🌈 Pixel Art Lighting. Contribute to NullTale/LutLight2D development by creating an account on GitHub.

prime loom
#

The node snaps any fragment information to the texel, so it works the same for shadows, light attenuation, specular and everything

#

Even stuff not related to lighting at all

vocal delta
#

Ya i'm trying to follow that. I'm on unity 6.3 and there are... some errors while following these. I guess bcoz it's from an older version
Just letting copilot deal with it for now. Eating a lot of grains of salt while doing so

#

1 of the root error is it's complaining for the use of ddx ddy function in here

{
    // 1.) Calculate how much the texture UV coords need to
    //     shift to be at the center of the nearest texel.
    float2 originalUV = UV0.xy;
    float2 centerUV = floor(originalUV * (TexelSize.zw))/TexelSize.zw + (TexelSize.xy/2.0);
    float2 dUV = (centerUV - originalUV);

    // 2b.) Calculate how much the texture coords vary over fragment space.
    //      This essentially defines a 2x2 matrix that gets
    //      texture space (UV) deltas from fragment space (ST) deltas
    // Note: I call fragment space "ST" to disambiguate from world space "XY".
    float2 dUVdS = ddx( originalUV );
    float2 dUVdT = ddy( originalUV );

    // 2c.) Invert the texture delta from fragment delta matrix
    float2x2 dSTdUV = float2x2(dUVdT[1], -dUVdT[0], -dUVdS[1], dUVdS[0])*(1.0f/(dUVdS[0]*dUVdT[1]-dUVdT[0]*dUVdS[1]));

    // 2d.) Convert the texture delta to fragment delta
    float2 dST = mul(dSTdUV , dUV);

    // 2e.) Calculate how much the world coords vary over fragment space.
    float3 dXYZdS = ddx(WorldPos);
    float3 dXYZdT = ddy(WorldPos);

    // 2f.) Finally, convert our fragment space delta to a world space delta
    // And be sure to clamp it in case the derivative calc went insane
    float3 dXYZ = dXYZdS * dST[0] + dXYZdT * dST[1];
    dXYZ = clamp (dXYZ, -1, 1);

    // 3a.) Transform the snapped UV back to world space
    SnappedWorldPos = (WorldPos + dXYZ);
}```
I guess bcoz this is in a subgraph, and it's ambiguous whether it's being called in fragment vertex or fragment (the main graph, is connected to fragment)
How can this be defined in 6.3?
#

I wonder if i should just attempt to recreate this whole thing in shadergraph nodes. There is apparently a ddxy node?

vocal delta
#

Ok it compiles now. But it's just grey...
But when i change to a texture with shape, the alpha seems to work

#

Ok wait2 gonna try things. Some things are working a bit more

vocal delta
vocal delta
#

OMG it works!!

vocal delta
#

I guess generally, the general shadow shape uses the shadow resolution (which may not be enough to define a diagonal shape), and this low res, blocky shadow, is what's then gets texel snapped

#

And smoothness 0 is better to disable the specular(?) light. Altho i'm wondering if the specular can also be texel snapped

#

And actually maybe too early to celebrate
The shadow is still not correct. There's a double shadow happening, and this 2nd shadowing is still a normal shadow. In the pic there's that tilted rectangle shadow overlapping around the same space as the texel snapped shadow

prime loom
#

Can only guess otherwise

vocal delta
#

Aah this is why, on the black part of the texture, only this "normal, unsnapped" shadow is visible

The texel snapped shadow can only be seen on the texture part that's not black

prime loom
# vocal delta

It's because this is a Lit graph
So you're calculating and applying lighting twice, snapped lighting on top of the typical one

vocal delta
#

Eh wait so it's supposed to be in a unlit?

#

But if i set to Unlit, there's no lighting and shadows at all

#

Oh ok got it

vocal delta
#

Ok cool. So now i'm gonna spend some time really understanding the hlsl snapped thing, and figure out how to apply this to the... lit-ness of the object itself?
Like this sphere i'd want the shaded gradient part to also be on its texel space

#

Someone mentioned in the forum post to also apply this to the normal channel
And... wow i'm so new to this custom lighting thing so i'm gonna read the unity page about it now

vocal delta
#

I haven't got to this yet and went straight to trying it on terrain, but i can't figure out

#

Or rather, copilot can't figure it out

#

OOOH nvm it works hahahhahaha

prime loom
#

Might need to consider that Terrain layers are not guaranteed to be the same resolution

vocal delta
#

Yes it's done. It takes _Splat0
Now just need to uhh apply it for all the splat texs

prime loom
vocal delta
#

Well i know for sure that all the terrain's splat tex will have the same res. So i guess even if i leave it to take splat0's texelSize it'll be fine

#

Pretty much done

#

With a little bump

#

Cooool ok. Now what's next

#

I guess i wanna report this to the forum thread, since the original guy gave up on making it work for terrain

prime loom
#

Or at least was before 6.3. introduced Terrain Shader Graphs templates which from my understanding allow custom lighting without excluding Terrain features like Shader Graph used to do

vocal delta
#

I was aiming to modify the lighting itself yes, so microsplat would pick it up too
But actually not sure where to do that

#

This is what i did

#

In TerrainLitPasses.hlsl

    InputData inputData;
    InitializeInputData(IN, normalTS, inputData);
    

#if defined(_TEXEL_SNAP)
    // --- Texel snap: snap world position BEFORE GI / shadow sampling so lighting and shadows use snapped position
    float2 uvForSnap = IN.uvSplat01.xy; // base/control UV for snapping
    float4 texelSize = _Splat0_TexelSize; //_Control_TexelSize; // control/splat texel-size uniform (use other _SplatN_TexelSize if desired)
    ApplyTexelSnapWS(inputData.positionWS, uvForSnap, inputData, texelSize);
#endif
    
    SetupTerrainDebugTextureData(inputData, IN.uvMainAndLM.xy);

Add this in TerrainDetailLitInput.hlsl

half4 _MainTex_TexelSize;

Made TexelSnapUtils.hlsl


// Generic world-space texel snap helper.
// worldPos: original world position for the fragment/pixel
// uv: the UV to snap to (caller decides which texture's UV to use)
// tex: the Texture2D to derive texel size from (pass the texture property, e.g. _BaseMap)
// inputData: the InputData used by lighting; this will be mutated to use snapped position.
void ApplyTexelSnapWS(float3 worldPos, float2 uv, inout InputData inputData, float4 texelSize)
{
#ifdef _TEXEL_SNAP
    float3 snappedPos;
    TexelSnap_float(worldPos, float4(uv, 0, 0), texelSize, snappedPos);

    // Replace the position used by lighting and recompute dependent values
    inputData.positionWS = snappedPos;
    inputData.viewDirectionWS = GetWorldSpaceNormalizeViewDir(inputData.positionWS);

    // Ensure shadow sampling uses snapped position
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) || defined(MAIN_LIGHT_CALCULATE_SHADOWS)
        inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
#else
        inputData.shadowCoord = float4(0, 0, 0, 0);
#endif

    // NOTE: fogCoord, baked GI inputs, probe sampling, etc. may also depend on positionWS.
    // Recompute them in the caller if you require them to match the snapped position.
#endif
}

#

And... idk how to modify the lighting itself but... since microsplat doesn't have shadergraph, i reckon i'll have to change MS' shader via non shadergraph too

prime loom
#

But I'm not sure if that's totally helpful, if the snapping of the lighting has to be done later than the light loop, anyway

vocal delta
#

Ooh ya i had this tab open but haven't properly read. I went ahead to try "just do the trick from the forum, but onto the terrain" as a start
Yes as planned, gonna try achieving this by the lighting itself and if this works, gonna be even more done with everything