PictureFrameBuilder/Shader: lighting parity, HTrace GBuffer pass, absolute frame metrics
Shader (PictureTessellationLit): - Lighting parity with URP Lit: lightmaps, shadowmask/mixed, APV, DBuffer decals, vertex additional lights, rendering layers, fragment fog - UniversalGBuffer pass (with tessellation + graded albedo) so HTrace WSGI composes correct GI instead of a cyan veil over pictures - Skip GPU tessellation entirely when strength/displacement is 0 - Inspector ranges matched to builder (-3..3 bump, -10..10 tessellation) Builder: - Frame Thickness & Padding are now absolute meters (size-independent) instead of fractions of the picture size - Tooltip updates for the new default/range semantics Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0c7ac11023
commit
57a4627b81
2 files changed
+308
-42
No files matched your search
@@ -6,10 +6,10 @@ namespace Chameleon.Components
|
||||
// Procedural picture frame, generated live in the editor (and at runtime) from the inspector
|
||||
// parameters. Sizing is inside-out: the picture keeps the texture's aspect ratio EXACTLY and the
|
||||
// outer frame grows around it by padding + thickness (Size = longer outer side) - insetting a
|
||||
// uniform border from an aspect-scaled outer rect would distort the picture. All shape parameters
|
||||
// are relative fractions (thickness/padding of the picture's longer side, radius of the maximum
|
||||
// possible rounding, depths of the frame depth), so a frame keeps its proportions when resized via
|
||||
// Size - resize via Size, NOT via transform scale. Four submeshes with their own
|
||||
// uniform border from an aspect-scaled outer rect would distort the picture. Thickness and padding
|
||||
// are absolute meters (independent of Size - the picture shrinks as they grow); corner radius is a
|
||||
// fraction of the maximum possible rounding and the depths are fractions of the frame depth.
|
||||
// Resize via Size, NOT via transform scale. Four submeshes with their own
|
||||
// material slots: 0 picture, 1 inner cavity (recess walls + padding ring), 2 frame (front ring, outer
|
||||
// sides, edge rounding), 3 back plate. Front faces -Z like Unity's built-in Quad. An assigned
|
||||
// PictureTexture becomes the picture material's base map via a per-frame DontSave material
|
||||
@@ -46,8 +46,8 @@ namespace Chameleon.Components
|
||||
[SerializeField] Vector2 _aspect = Vector2.one;
|
||||
|
||||
[Header("Frame")]
|
||||
[Tooltip("Border width of the frame as a fraction of the picture's longer side.")]
|
||||
[SerializeField, Range(0f, 1f)] float _frameThickness = 0.05f;
|
||||
[Tooltip("Border width of the frame in meters (independent of Size).")]
|
||||
[SerializeField, Range(0.001f, 0.5f)] float _frameThickness = 0.03f;
|
||||
[Tooltip("Depth of the frame, front face to back face.")]
|
||||
[SerializeField, Range(0.002f, 0.500f)] float _frameDepth = 0.05f;
|
||||
[Tooltip("Rounding of the outer frame edges relative to the maximum possible radius (thickness / half depth); 0 = sharp box, 1 = fully rounded.")]
|
||||
@@ -58,27 +58,27 @@ namespace Chameleon.Components
|
||||
[SerializeField, Range(-1f, 1f)] float _frameInnerDepth = -0.1f;
|
||||
|
||||
[Header("Picture")]
|
||||
[Tooltip("Gap between the frame's inner edge and the picture as a fraction of the picture's longer side.")]
|
||||
[SerializeField, Range(0f, 1f)] float _padding = 0.01f;
|
||||
[Tooltip("Gap between the frame's inner edge and the picture in meters (independent of Size).")]
|
||||
[SerializeField, Range(0f, 0.5f)] float _padding = 0.005f;
|
||||
[Tooltip("Picture plane: -1 = fully inside (on the back plate), 0 = flush with the inner floor, 1 = a full frame depth in front of the frame.")]
|
||||
[SerializeField, Range(-1f, 1f)] float _pictureDepth = 0.1f;
|
||||
[Tooltip("Photo for this frame: applied as the picture material's base map via a per-frame material instance (the material asset itself is never modified) and drives the aspect ratio. Empty = the material's own base map is shown.")]
|
||||
[SerializeField] Texture _pictureTexture;
|
||||
[Tooltip("Optional normal map for the picture: applied as the picture material's bump map via the same per-frame material instance.")]
|
||||
[SerializeField] Texture _pictureNormalMap;
|
||||
[Tooltip("Intensity of the picture normal map (URP _BumpScale). 1 = as authored.")]
|
||||
[SerializeField, Range(0f, 3f)] float _normalMapStrength = 1f;
|
||||
[Tooltip("Intensity of the picture normal map (URP _BumpScale). 0 = flat, negative inverts the relief.")]
|
||||
[SerializeField, Range(-3f, 3f)] float _normalMapStrength = 0;
|
||||
[Tooltip("Optional height map for the picture: set as _HeightMap on the per-frame material instance (tessellation shader); on plain URP Lit it falls back to the parallax map.")]
|
||||
[SerializeField] Texture _pictureHeightMap;
|
||||
[Tooltip("Scales the material's occlusion (_OcclusionStrength). 1 = as authored.")]
|
||||
[SerializeField, Range(0f, 3f)] float _occlusionStrength = 1f;
|
||||
[Tooltip("Scales the material's occlusion (_OcclusionStrength). 0 = no occlusion darkening.")]
|
||||
[SerializeField, Range(0f, 3f)] float _occlusionStrength = 0;
|
||||
[Tooltip("Contrast of the occlusion map around mid-gray (_OcclusionContrast). 0 = unchanged, -1 = flat, 3 = strongly exaggerated.")]
|
||||
[SerializeField, Range(-1f, 3f)] float _occlusionContrast;
|
||||
[Tooltip("Brightness multiplier on the picture base map (_Brightness) to compensate the darkening from occlusion. 1 = unchanged.")]
|
||||
[SerializeField, Range(0f, 3f)] float _brightness = 1f;
|
||||
[Tooltip("Scales the material's tessellation displacement (_TessellationStrength). 1 = as authored.")]
|
||||
[SerializeField, Range(0f, 10f)] float _tessellationStrength = 1f;
|
||||
[Tooltip("Triangle grid resolution of the picture plane (cells along its longer side); raise it so displacement/tessellation has vertices to work with. 1 = plain quad.")]
|
||||
[SerializeField, Range(0f, 3f)] float _brightness = 1;
|
||||
[Tooltip("Scales the material's tessellation displacement (_TessellationStrength). 0 = flat (GPU tessellation is skipped entirely), negative inverts the relief.")]
|
||||
[SerializeField, Range(-10f, 10f)] float _tessellationStrength = 0;
|
||||
[Tooltip("Triangle grid resolution of the picture plane mesh (cells along its longer side). 1 = plain quad; extra triangles visible in wireframe beyond this come from the shader's GPU Tessellation Factor, not this mesh.")]
|
||||
[SerializeField, Range(1, 10)] int _pictureSubdivisions = 1;
|
||||
|
||||
[Header("Picture Crop")]
|
||||
@@ -162,13 +162,13 @@ namespace Chameleon.Components
|
||||
ResolveAspect();
|
||||
#endif
|
||||
// Inside-out sizing: the picture keeps the texture aspect exactly; thickness and padding
|
||||
// are fractions of the picture's longer side, and Size stays the longer OUTER side:
|
||||
// size = pLong + 2*(t + pad) = pLong * (1 + thickness + padding). No clamp dead zones -
|
||||
// every 0..1 combination yields valid geometry.
|
||||
// are absolute meters (they do NOT scale with Size), and Size stays the longer OUTER
|
||||
// side: pLong = size - 2*(t + pad), clamped so the picture never degenerates (the outer
|
||||
// side then exceeds Size instead).
|
||||
float d = Mathf.Max(_frameDepth, 0.002f);
|
||||
float pLong = Mathf.Max(_size, 0.01f) / (1f + _frameThickness + _padding);
|
||||
float t = Mathf.Max(_frameThickness * pLong * 0.5f, 0.001f);
|
||||
float pad = _padding * pLong * 0.5f;
|
||||
float t = Mathf.Max(_frameThickness, 0.001f);
|
||||
float pad = Mathf.Max(_padding, 0f);
|
||||
float pLong = Mathf.Max(Mathf.Max(_size, 0.01f) - 2f * (t + pad), 0.01f);
|
||||
float pw = Mathf.Max(pLong * _aspect.x, 0.001f);
|
||||
float ph = Mathf.Max(pLong * _aspect.y, 0.001f);
|
||||
float ow = pw + 2f * pad;
|
||||
|
||||
Reference in new issue
Block a user