IndieDoroid

Hi Harald

If you feel like taking up the challenge ...

Is there a way to activate Specular based calculations rather than Metallic, in the Spine URP shaders?

I was reading this.
https://docs.unity3d.com/Manual/StandardShaderMaterialParameterMetallic.html
Instead, the Metallic levels for the material are controlled by the values in the Red channel of the texture, and the Smoothness levels for the material are controlled by the Alpha channel of the texture.
But even after making the GBA channels pure black.. I still can't successfully mask out specific sections.

Thanks for your help
metallic.jpg

speciu.jpg


spine.jpg
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
Avatar
IndieDoroid
  • Postovi: 249

Harald

IndieDoroid je napisao/la:I think the original Spine Shader creator (before you took over) didn't know the difference in Unity?
I think he was pretty aware of it :). Enabling the Specular parameter at the Sprite shaders does not switch between a PBR specular vs PBR metallic workflow, it switches from simple diffuse lambert shading to PBR shading including specular reflections. Admittedly the parameter name is perhaps a bit misleading, technically it's "PBR shading with Mecallic workflow".

Adding an additional option to enable Specular PBR workflow in addition to the metallic workflow is not very beneficial, since the Metallic workflow just simplifies it to use the albedo color as the specular reflectance color. You would rarely want to specify a custom specular reflectance color.
The Unity documentation page is not very good in explaining the whole picture unfortunately.
There are much better explanations available online, such as the Marmoset PBR page here:
https://marmoset.co/posts/physically-based-rendering-and-you-can-too/
IndieDoroid je napisao/la:But even after making the GBA channels pure black.. I still can't successfully mask out specific sections.
What you most likely want is not to change the specular reflectance color in certain areas, this will turn shiny metal into shiny plastic. What you want instead is to make these areas rough instead of glossy, thus setting the alpha (glossiness) channel to black to make it completely rough.

The specular workflow would also lead to the same result setting the Specular reflectance color to 0 as when you set the Metallic value to 0.
float3 f0 = float3(0.04, 0.04, 0.04);
float3 diffuseColor = baseColor.rgb * (float3(1.0, 1.0, 1.0) - f0);
diffuseColor *= 1.0 - metallic;
float3 specularColor = lerp(f0, baseColor.rgb, metallic);
If by "mask out specific sections" you mean you want lambert shading in some areas and PBR shading in shiny areas, then you would need to modify the whole shader in the following way:
float4 lambertResult = lambertShading(..);
float4 pbrResult = pbrShading(..);
float4 combinedResult = lerp(lambertResult, pbrResult, glossiness);
Currently the two shading branches are completely separated via #if _SPECULAR <pbr part> #else <lambert part> preprocessor branches. I doubt however that that's really a good idea. :nerd:
Avatar
Harald

Harri
  • Postovi: 3992

IndieDoroid

Harald je napisao/la:There are much better explanations available online, such as the Marmoset PBR page here:
https://marmoset.co/posts/physically-based-rendering-and-you-can-too/
Whoohoo! Thanks for the link and explanation Harald. I think I read that article last year, but it totally went over my head. :lol:
I'll have to go over it again, now that I'm dipping toes into URP \ PBR land.
Harald je napisao/la:
float4 lambertResult = lambertShading(..);
float4 pbrResult = pbrShading(..);
float4 combinedResult = lerp(lambertResult, pbrResult, glossiness);
Ok I'll try this out and see if it works. Do I just paste this into any section of the "Spine/Sprite/Pixel Lit" shader? I don't see any code snippets to edit, otherwise.

Also is the "Spine/Sprite/Pixel Lit" script, the one used by URP? I don't see a shader folder specifically for URP stuff. :hmm:

and yea in regards to "masking out", the goal is to have like "shiny" eyes, "less shiny" face and "no shiny" socks etc.

Just out of curiosity, is there a reason this code isn't enabled by default in the Spine shader? :think:

Thanks for the help again ! :whew:
Avatar
IndieDoroid
  • Postovi: 249

Harald

IndieDoroid je napisao/la:Ok I'll try this out and see if it works. Do I just paste this into any section of the "Spine/Sprite/Pixel Lit" shader? I don't see any code snippets to edit, otherwise.

Also is the "Spine/Sprite/Pixel Lit" script, the one used by URP? I don't see a shader folder specifically for URP stuff. :hmm:
No to both questions.
The shader is Spine-Sprite-URP.shader in the URP package:
https://github.com/EsotericSoftware/spine-runtimes/blob/4.0/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Spine-Sprite-URP.shader

The actual fragment shader code is in included via #include "Include/Spine-Sprite-ForwardPass-URP.hlsl" here.

The two code branches are here and here
#if defined(_SPECULAR)
...
pixel = LightweightFragmentPBRSimplified(..)
#else
...
pixel = LightweightFragmentBlinnPhongSimplified(..)
#endif


So you would need to execute both code paths and then lerp() the result as described in my above posting.
Avatar
Harald

Harri
  • Postovi: 3992

IndieDoroid

Hi Harald

Ok I'm trying it out now. Pls bear in mind most of my coding knowledge is C# based.. so shader coding is still alien to me.

I am getting red errors, obviously something isn't right. But can you take a look at the shader changes? What is causing the red error? The console isn't very helpful.. Unity just says
Shader error in 'Universal Render Pipeline/Spine/Sprite': undeclared identifier 'LightweightFragmentBlinnPhongSimplified' at /ProjectY/Packages/com.esotericsoftware.spine.urp-shaders-4.0-Unity2019.3-2021-12-10/Shaders/Include/Spine-Sprite-ForwardPass-URP.hlsl(262) (on d3d11) ....
I combined both the two branches as you suggested and inserted the lerp snippet from your previous post. Is this the right way to do it?
#if defined(SPECULAR)
half2 metallicGloss = getMetallicGloss(input.texcoord.xy);
half metallic = metallicGloss.x;
half smoothness = metallicGloss.y; // this is 1 minus the square root of real roughness m.

half3 specular = half3(0, 0, 0);
half4 emission = half4(0, 0, 0, 1);
APPLY_EMISSION_SPECULAR(emission, input.texcoord.xy)
half4 pixelPBR = LightweightFragmentPBRSimplified(inputData, texureColor, metallic, specular, smoothness, emission.rgb, input.vertexColor);

half3 emissionA = half3(0, 0, 0);
APPLY_EMISSION(emissionA, input.texcoord.xy)


//LINE 262 --- isn't pixelLam declared here? :\
half4 pixelLam = LightweightFragmentBlinnPhongSimplified(inputData, texureColor, emissionA, input.vertexColor);
//LINE 262

float4 _lambertResult = pixelLam;
float4 _pbrResult = pixelPBR;
float4 _test = lerp(_lambertResult, _pbrResult, metallicGloss);
#endif
later on down the shader I get a red error telling me the return is incorrect.
#if defined(_RIM_LIGHTING)
_test.rgb = applyRimLighting(input.positionWS.xyz, normalWS, _test);
#endif

COLORISE(_test)
APPLY_FOG_LWRP(_test, input.fogFactorAndVertexLight.x)

return _test;
}
I'm not sure if I should be returning _test from the specular "branch" ? In the original shader its returning
//#if defined(_RIM_LIGHTING)
// pixel.rgb = applyRimLighting(input.positionWS.xyz, normalWS, pixel);
//#endif
//
// COLORISE(pixel)
// APPLY_FOG_LWRP(pixel, input.fogFactorAndVertexLight.x)
//
// return pixel;
//}
However, this pixel was only found in the
//#if defined(SPECULAR)
// half2 metallicGloss = getMetallicGloss(input.texcoord.xy);
// half metallic = metallicGloss.x;
// half smoothness = metallicGloss.y; // this is 1 minus the square root of real roughness m.
//
// half3 specular = half3(0, 0, 0);
// half4 emission = half4(0, 0, 0, 1);
// APPLY_EMISSION_SPECULAR(emission, input.texcoord.xy)
// half4 pixel = LightweightFragmentPBRSimplified(inputData, texureColor, metallic, specular, smoothness, emission.rgb, input.vertexColor);
//#else
// half3 emission = half3(0, 0, 0);
// APPLY_EMISSION(emission, input.texcoord.xy)
// half4 pixel = LightweightFragmentBlinnPhongSimplified(inputData, texureColor, emission, input.vertexColor);
//#endif
branch, as far as I could tell. Which I now changed to the _test lerp

Thanks for the help! :)
Avatar
IndieDoroid
  • Postovi: 249

Harald

Sorry for the late reply.
IndieDoroid je napisao/la: The console isn't very helpful.. Unity just says
Shader error in 'Universal Render Pipeline/Spine/Sprite': undeclared identifier 'LightweightFragmentBlinnPhongSimplified' at /ProjectY/Packages/com.esotericsoftware.spine.urp-shaders-4.0-Unity2019.3-2021-12-10/Shaders/Include/Spine-Sprite-ForwardPass-URP.hlsl(262) (on d3d11) ....
Well, it's actually very helpful, it says that it is not declared before it's used on line 262. So some of the #if / #else branches (most likely #if defined(SPECULAR)) in the included files must have led to the definition of LightweightFragmentBlinnPhongSimplified being removed. So you need to move the LightweightFragmentBlinnPhongSimplified method definition code to somewhere outside of those preprocessor branches that are stripped away when you enable the SPECULAR define.

In general you need to be sure that with your current defines, all included files inlined, and the respective #if / #else code sections being active, everything must compile as if it were written in a single long file.
IndieDoroid je napisao/la:I combined both the two branches as you suggested and inserted the lerp snippet from your previous post. Is this the right way to do it?
It's not completely wrong. However you are lerping with metallicGloss as lerp factor, which is a 2D vector, containing metallic in the first component. You need to use smoothness instead, or explicitly use metallicGloss.y.
later on down the shader I get a red error telling me the return is incorrect.
This could be a follow-up problem. In general please always include the error message, never rephrase error descriptions unless you fully understand what they are saying.
I'm not sure if I should be returning _test from the specular "branch" ?
You just need to ensure that all shader branches return the right values, the way you do that is up to you :). You could early-out return a new variable, or assign a common returned variable. Whatever you prefer.
Avatar
Harald

Harri
  • Postovi: 3992


Natrag na Unity