From 82888d0771592e17dbd17ae172b21f4277b5098f Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Mon, 17 Apr 2023 13:37:11 -0700 Subject: [PATCH 01/20] Imposter nodes and documents --- .../Documentation~/Imposter-Sample-Node.md | 65 +++ .../Documentation~/Imposter-UV-Node.md | 65 +++ .../Documentation~/previews/ImposterSample.md | 19 + .../Documentation~/previews/ImposterUV.md | 20 + .../Input/MeshDeformation/Imposter.hlsl | 410 ++++++++++++++++++ .../Input/MeshDeformation/Imposter.hlsl.meta | 7 + .../MeshDeformation/ImposterSampleNode.cs | 126 ++++++ .../ImposterSampleNode.cs.meta | 11 + .../Input/MeshDeformation/ImposterUVNode.cs | 124 ++++++ .../MeshDeformation/ImposterUVNode.cs.meta | 11 + 10 files changed, 858 insertions(+) create mode 100644 com.unity.sg2/Documentation~/Imposter-Sample-Node.md create mode 100644 com.unity.sg2/Documentation~/Imposter-UV-Node.md create mode 100644 com.unity.sg2/Documentation~/previews/ImposterSample.md create mode 100644 com.unity.sg2/Documentation~/previews/ImposterUV.md create mode 100644 com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl create mode 100644 com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl.meta create mode 100644 com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs create mode 100644 com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs.meta create mode 100644 com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs create mode 100644 com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs.meta diff --git a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md new file mode 100644 index 00000000000..caec0ba3b9e --- /dev/null +++ b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md @@ -0,0 +1,65 @@ +# Imposter Sample Node + +## Description + +The Imposter Sample Node utilizes the three virtual UVs to sample the imposter texture and blends them based on the camera intersection point on the octahedron sphere, thereby achieving accurate sampling results. +## Ports + +| Name | Direction | Type | Description | +|:------------ |:-------------|:-----|:---| +| Texture | Input | Texture2D | The texture asset to sample | +| Sampler | Input | Sampler State | The texture sampler to use for sampling the texture | +| UV0 | Input | Vector4 | The virtual UV for the base frame | +| UV1 | Input | Vector4 | The virtual UV for the second frame | +| UV2 | Input | Vector4 | The virtual UV for the third frame | +| Grid | Input | Vector4 | The current UV grid, which is used to find the corresponding sample frames | +| Frames | Input | Float | The amount of the imposter frames | +| Clip | Input | Float | The amount of clipping for a single frame | +| Parallax | Input | Float | Parallax strength| +| Height Map Channel | Input | Int | The channle of the height map to sample for parallax mapping, if any| +| RGBA | Output | Vector3 | A vector4 from the sampled texture | + +## Controls + +The Imposter Sample Node [!include[nodes-controls](./snippets/nodes-controls.md)] + + + + + + + + + + + + + + + + + + + + + + + + +
NameSample TypeDescription
TypeDropdownSelect whether to sample three frames or one frame.
Three FramesBlends between three frames to get the smoothest result.
One FrameCalculates only one frame for better performance.
+ +## Generated code example + +[!include[nodes-generated-code](./snippets/nodes-generated-code.md)], based on the selected Mode on the Imposter Sample Node node: + +### ThreeFrames + +``` +ImposterSample(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); +``` + +### OneFrame + +``` +ImposterSample_oneFrame(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, Sampler.samplerstate, RGBA); +``` diff --git a/com.unity.sg2/Documentation~/Imposter-UV-Node.md b/com.unity.sg2/Documentation~/Imposter-UV-Node.md new file mode 100644 index 00000000000..2475bd6df72 --- /dev/null +++ b/com.unity.sg2/Documentation~/Imposter-UV-Node.md @@ -0,0 +1,65 @@ +# Imposter UV Node + +## Description + +The Imposter UV Node calculates the billboard positon and the virtual UVs for sampling. +## Ports + +| Name | Direction | Type | Description | +|:------------ |:-------------|:-----|:---| +| In Position | Input | Vector3 | The postion in Object space | +| UV | Input | Vector4 | The UV coordinates of the mesh | +| Frames | Input | Float | The amount of the imposter frames | +| Offset | Input | Float | The offset value from the pivot | +| Size | Input | Float | The size of the imposter | +| HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type | +| Out Positon | Output | Vector3 | The output billboard position | +| UV0 | Output | Vector4 | The virtual UV for the base frame | +| UV1 | Output | Vector4 | The virtual UV for the second frame | +| UV2 | Output | Vector4 | The virtual UV for the third frame | +| Grid | Output | Vector4 | The current UV grid, which is used to find the corresponding sample frames | + + +## Controls + +The Imposter UV Node [!include[nodes-controls](./snippets/nodes-controls.md)] + + + + + + + + + + + + + + + + + + + + + + + + +
NameSample TypeDescription
TypeDropdownSelect whether to sample three frames or one frame.
Three FramesBlends between three frames to get the smoothest result.
One FrameCalculates only one frame for better performance.
+ +## Generated code example + +[!include[nodes-generated-code](./snippets/nodes-generated-code.md)], based on the selected Mode on the Imposter Sample Node node: + +### ThreeFrames + +``` +ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, OutPos, Grid, UV0, UV1, UV2)``` + +### OneFrame + +``` +ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, HemiSphere, OutPos, Grid, UV0); +``` diff --git a/com.unity.sg2/Documentation~/previews/ImposterSample.md b/com.unity.sg2/Documentation~/previews/ImposterSample.md new file mode 100644 index 00000000000..214c37725c1 --- /dev/null +++ b/com.unity.sg2/Documentation~/previews/ImposterSample.md @@ -0,0 +1,19 @@ +## Description +Samples from the three virtual UVs and blends them base on the camera intersection point to get the correct result. +## Inputs +**Texture** - The texture asset to sample. +**Sampler** - The texture sampler to use for sampling the texture. +**UV0** - The virtual UV for the base frame. +**UV1** - The virtual UV for the second frame. +**UV2** - The virtual UV for the third frame. +**Grid** - The current UV grid, which is used to find the corresponding sample frames. +**Frames** - The amount of the imposter frames +**Clip** - The amount of clipping for a single frame. +**Parallax** - Parallax strength. +**Height Map Channel** - The channle of the height map to sample for parallax mapping, if any. + +## Output +**RGBA** - A vector4 from the sampled texture. + +## Controls +**Sample Type** - Select whether to sample three frames or one frame, three frames for smoother result, one frame for better performance. diff --git a/com.unity.sg2/Documentation~/previews/ImposterUV.md b/com.unity.sg2/Documentation~/previews/ImposterUV.md new file mode 100644 index 00000000000..43d892ea3df --- /dev/null +++ b/com.unity.sg2/Documentation~/previews/ImposterUV.md @@ -0,0 +1,20 @@ +## Description +Calculates the billboard positon and the virtual UVs for sampling. + +## Inputs +**InPosition** - The postion in Object space. +**UV** - The UV coordinates of the mesh. +**Frames** - The amount of the imposter frames +**Offset** - The offset value from the pivot. +**Size** - The size of the imposter. +**HemiSphere** - If it's true, calculates the imposter grid and UVs base on hemisphere type. + +## Output +**OutPosition** - The output billboard position. +**UV0** - The virtual UV for the base frame. +**UV1** - The virtual UV for the second frame. +**UV2** - The virtual UV for the third frame. +**Grid** - The current UV grid using to find the sample frames. + +## Controls +**Sample Type** - Select whether to sample three frames or one frame, three frames for smoother result, one frame for better performance. diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl new file mode 100644 index 00000000000..66e3fd20cf2 --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl @@ -0,0 +1,410 @@ +#ifndef IMPOSTERSTART +#define IMPOSTESTART + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Sampling.hlsl" +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ParallaxMapping.hlsl" + +struct Ray +{ + float3 Origin; + float3 Direction; +}; + +float3 CoordToHemi(float2 coord) +{ + coord = float2(coord.x + coord.y, coord.x - coord.y) * 0.5; + float3 dir = float3(coord.x, 1 - dot(float2(1, 1), abs(coord.xy)), coord.y); + return dir; +} + +float3 CoordToOcta(float2 coord) +{ + float3 dir = float3(coord.x, 1 - dot(1, abs(coord)), coord.y); + if (dir.y < 0) + { + float2 flip = dir.xz >= 0 ? float2(1, 1) : float2(-1, -1); + dir.xz = (1 - abs(dir.zx)) * flip; + } + return dir; +} + +float3 GridToVector(float2 coord, bool IsHemi) +{ + float3 dir; + if (IsHemi) + { + dir = CoordToHemi(coord); + } + else + { + dir = CoordToOcta(coord); + } + return dir; +} + +//for hemisphere +float2 VectorToHemi(float3 dir) +{ + dir.xz /= dot(1.0, abs(dir)); + return float2(dir.x + dir.z, dir.x - dir.z); +} + +float2 VectorToOcta(float3 dir) +{ + dir.xz /= dot(1, abs(dir)); + if (dir.y <= 0) + { + dir.xz = (1 - abs(dir.zx)) * (dir.xz >= 0 ? 1.0 : -1.0); + } + return dir.xz; +} + +//weights base on the triangle +float4 CalculateWeights(float2 uv) +{ + uv = frac(uv); + + float2 oneMinusUV = 1 - uv.xy; + + float4 res; + //frame 0 + res.x = min(oneMinusUV.x, oneMinusUV.y); + //frame 1 + res.y = abs(dot(uv, float2(1.0, -1.0))); + //frame 2 + res.z = min(uv.x, uv.y); + //mask + res.w = saturate(ceil(uv.x - uv.y)); + + return res; +} + +float3 FrameTransformLocal(float3 BillboardPosToCam, float3 normal, out float3 worldX, out float3 worldZ) +{ + float3 upVector = float3 (0, 1, 0); + worldX = normalize(cross(upVector, normal)); + worldZ = normalize(cross(worldX, normal)); + + BillboardPosToCam *= -1.0; + + float3x3 worldToLocal = float3x3(worldX, worldZ, normal); + float3 localRay = normalize(mul(worldToLocal, BillboardPosToCam)); + return localRay; +} + +float2 PlaneIntersectionUV(float3 planeNormal, float3 planeX, float3 planeZ, float3 center, float2 UVscale, Ray ray) +{ + float normalDotOrigin = dot(planeNormal, -ray.Origin);//(p0 - l0) . n + float normalDotRay = dot(planeNormal, ray.Direction);//l.n + float planeDistance = normalDotOrigin / normalDotRay;//distance >0 then intersecting + + //intersect = rayDir * distance + rayPos + float3 intersection = ((ray.Direction * planeDistance) + ray.Origin) - center; + + float dx = dot(planeX, intersection); + float dz = dot(planeZ, intersection); + + float2 uv = float2(0, 0); + + if (planeDistance > 0) + { + uv = -float2(dx, dz); + } + else + { + uv = float2(0, 0); + } + + uv /= UVscale; + uv += float2(0.5, 0.5); + return uv; +} + +float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) +{ + float3 up = normalize(objectSpaceCameraDir); + float3 x = normalize(cross(up, float3(0.0, 1.0, 0.0))); + float3 z = normalize(cross(x, up)); + + uv = uv * 2.0 - 1.0; + + float3 newX = x * uv.x; + float3 newZ = z * uv.y; + + float3 result = newX + newZ; + + return result; +} + +//Calculate Vertex postion and UVs +void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, + out float3 outPos, out float4 outUVGrid, out float4 outUV0, out float4 outUV1, out float4 outUV2) +{ + float framesMinusOne = imposterFrames - 1; + + //camera pos in object space + float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz; + float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); + + //get uv in a single frame + float2 UVscaled = inUV.xy * (1.0 / imposterFrames); + float2 size = imposterSize.xx * 2.0; + + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + + //camera to projection vector + float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; + + //BillboardPos position to camera ray + float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); + + Ray ray; + ray.Origin = objectSpaceCameraPos; + ray.Direction = rayDirLocal; + + //set up virtual grid + float2 grid; + if (isHemi) { + objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); + grid = VectorToHemi(objectSpaceCameraDir); + } + else { + grid = VectorToOcta(objectSpaceCameraDir); + } + + grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 + grid *= framesMinusOne;//multiply framesMinusOne to cover the texture + + float2 gridFrac = frac(grid); + float2 gridFloor = floor(grid); + + float4 weights = CalculateWeights(gridFrac); + + //set up for octahedron: + //1.find the nearest 3 frames + //2.base on the grid find the direction intersect with the octahedron + //3.construct the face/plane for that direction + //4.base on the plane and find the virtual uv coord + + //get the 3 nearest frames + float2 frame0 = gridFloor; + float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); + float2 frame2 = gridFloor + float2(1, 1); + + //convert frame coordinate to octahedron direction + float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); + float3 frame1ray = normalize(GridToVector(float2(frame1 / framesMinusOne * 2 - 1), isHemi)); + float3 frame2ray = normalize(GridToVector(float2(frame2 / framesMinusOne * 2 - 1), isHemi)); + + float3 center = float3(0, 0, 0); + + float3 plane0x; + float3 plane0normal = frame0ray; + float3 plane0z; + float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); + + float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); + vUv0 /= imposterFrames; + + float3 plane1x; + float3 plane1normal = frame1ray; + float3 plane1z; + float3 frame1local = FrameTransformLocal(BillboardPosToCam, frame1ray, plane1x, plane1z); + + float2 vUv1 = PlaneIntersectionUV(plane1normal, plane1x, plane1z, center, size, ray); + vUv1 /= imposterFrames; + + float3 plane2x; + float3 plane2normal = frame2ray; + float3 plane2z; + float3 frame2local = FrameTransformLocal(BillboardPosToCam, frame2ray, plane2x, plane2z); + + float2 vUv2 = PlaneIntersectionUV(plane2normal, plane2x, plane2z, center, size, ray); + vUv2 /= imposterFrames; + + frame0local.xy /= imposterFrames; + frame1local.xy /= imposterFrames; + frame2local.xy /= imposterFrames; + + //vert pos + outPos = BillboardPos + imposterOffset; + + //surface + outUVGrid.xy = UVscaled; + outUVGrid.zw = grid; + outUV0 = float4(vUv0.xy, frame0local.xz); + outUV1 = float4(vUv1.xy, frame1local.xz); + outUV2 = float4(vUv2.xy, frame2local.xz);; +} +void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, + out float3 outPos, out float4 outUVGrid, out float4 outUV0) +{ + float framesMinusOne = imposterFrames - 1; + + //camera pos in object space + float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz; + float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); + + //get uv in a single frame + float2 UVscaled = inUV.xy * (1.0 / imposterFrames); + float2 size = imposterSize.xx * 2.0; + + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + + //camera to projection vector + float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; + + //BillboardPos position to camera ray + float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); + + Ray ray; + ray.Origin = objectSpaceCameraPos; + ray.Direction = rayDirLocal; + + //set up virtual grid + float2 grid; + if (isHemi) { + objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); + grid = VectorToHemi(objectSpaceCameraDir); + } + else { + grid = VectorToOcta(objectSpaceCameraDir); + } + + grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 + grid *= framesMinusOne;//multiply framesMinusOne to cover the texture + + float2 gridFrac = frac(grid); + float2 gridFloor = floor(grid); + + float4 weights = CalculateWeights(gridFrac); + + //set up for octahedron: + //1.find the nearest 3 frames + //2.base on the grid find the direction intersect with the octahedron + //3.construct the face/plane for that direction + //4.base on the plane and find the virtual uv coord + + //get the 3 nearest frames + float2 frame0 = gridFloor; + float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); + float2 frame2 = gridFloor + float2(1, 1); + + //convert frame coordinate to octahedron direction + float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); + + float3 center = float3(0, 0, 0); + + float3 plane0x; + float3 plane0normal = frame0ray; + float3 plane0z; + float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); + + float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); + vUv0 /= imposterFrames; + + frame0local.xy /= imposterFrames; + + //vert pos + outPos = BillboardPos + imposterOffset; + + //surface + outUVGrid.xy = UVscaled; + outUVGrid.zw = grid; + outUV0 = float4(vUv0.xy, frame0local.xz); + +} +//Sample from UVs +void ImposterSample(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, + in float imposterClip, in float4 inUVGrid, in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) +{ + float2 inUV = inUVGrid.xy; + + float2 fracGrid = frac(inUVGrid.zw); + + float4 weights = CalculateWeights(fracGrid); + + float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; + + float2 frame0 = gridSnap; + float2 frame1 = gridSnap + (lerp(float2(0, 1), float2(1, 0), weights.w) / imposterFrames.xx); + float2 frame2 = gridSnap + (float2(1, 1) / imposterFrames.xx); + + float2 vp0uv = frame0 + inUV0.xy; + float2 vp1uv = frame1 + inUV1.xy; + float2 vp2uv = frame2 + inUV2.xy; + + //frame size ->2048/12 = 170.6 + float frameSize = mapTexelSize.z / imposterFrames; + //actual texture size used -> 170*12 = 2040 + float actualTextureSize = floor(frameSize) * imposterFrames; + //the scalar -> 2048/2040 = 0.99609375 + float scalar = mapTexelSize.z / actualTextureSize; + + vp0uv *= scalar; + vp1uv *= scalar; + vp2uv *= scalar; + + if (parallax != 0) { + + vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + vp1uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); + vp2uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); + } + + // clip out neighboring frames + float2 gridSize = 1.0 / imposterFrames.xx; + float2 bleeds = mapTexelSize.xy * imposterClip; + vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); + vp1uv = clamp(vp1uv, frame1 - bleeds, frame1 + gridSize + bleeds); + vp2uv = clamp(vp2uv, frame2 - bleeds, frame2 + gridSize + bleeds); + + float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)) * weights.x + + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp1uv, ddx(inUV), ddy(inUV)) * weights.y + + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp2uv, ddx(inUV), ddy(inUV)) * weights.z; + + outColor.a = blendedColor.a - imposterClip + 1; + clip(outColor.a); + outColor.rgb = blendedColor.rgb; +} + +void ImposterSample_oneFrame(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, + in float imposterClip, in float4 inUVGrid, in float4 inUV0, in SamplerState ss, out float4 outColor) +{ + float2 inUV = inUVGrid.xy; + + float2 fracGrid = frac(inUVGrid.zw); + + float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; + + float2 frame0 = gridSnap; + + float2 vp0uv = frame0 + inUV0.xy; + + //frame size ->2048/12 = 170.6 + float frameSize = mapTexelSize.z / imposterFrames; + //actual texture size used -> 170*12 = 2040 + float actualTextureSize = floor(frameSize) * imposterFrames; + //the scalar -> 2048/2040 = 0.99609375 + float scalar = mapTexelSize.z / actualTextureSize; + + vp0uv *= scalar; + + if (parallax != 0) { + + vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + } + + // clip out neighboring frames + float2 gridSize = 1.0 / imposterFrames.xx; + float2 bleeds = mapTexelSize.xy * imposterClip; + vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); + + float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)); + + outColor.a = blendedColor.a - imposterClip + 1; + clip(outColor.a); + outColor.rgb = blendedColor.rgb; +} + +#endif diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl.meta new file mode 100644 index 00000000000..6c340c1de4e --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1142271a2968b4249b58c9ba1e9012f7 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs new file mode 100644 index 00000000000..7f7459798cf --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs @@ -0,0 +1,126 @@ +using UnityEditor.ShaderGraph.GraphDelta; +using Usage = UnityEditor.ShaderGraph.GraphDelta.GraphType.Usage; + +namespace UnityEditor.ShaderGraph.Defs +{ + internal class ImposterSampleNode : IStandardNode + { + static string Name => "ImposterSampleNode"; + static int Version => 1; + public static NodeDescriptor NodeDescriptor => new( + Version, + Name, + "ImposterSample", + functions: new FunctionDescriptor[] { + new( + "ThreeFrames", + @"ImposterSample(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", + new ParameterDescriptor[] + { + new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), + new ParameterDescriptor("UV1", TYPE.Vec4, Usage.In), + new ParameterDescriptor("UV2", TYPE.Vec4, Usage.In), + new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), + new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), + new ParameterDescriptor("Clip", TYPE.Float, Usage.In, new float[] {1f}), + new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), + new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), + new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), + new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out) + }, + new string[] + { + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" + } + ), + new( + "OneFrame", + @"ImposterSample_oneFrame(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, Sampler.samplerstate, RGBA);", + new ParameterDescriptor[] + { + new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), + new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), + new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), + new ParameterDescriptor("Clip", TYPE.Float, Usage.In, new float[] {1f}), + new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), + new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), + new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), + new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out) + }, + new string[] + { + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" + } + ) + } + ); + + public static NodeUIDescriptor NodeUIDescriptor => new( + Version, + Name, + displayName: "Imposter Sample", + tooltip: "Samples from the three virtual UVs and blends them base on the camera intersection point to get the correct result.", + category: "Input/Mesh Deformation", + hasPreview: false, + description: "pkg://Documentation~/previews/ImposterSample.md", + synonyms: new string[] { "billboard" }, + selectableFunctions: new() + { + { "ThreeFrames", "Three Frames" }, + { "OneFrame", "One Frame" } + }, + functionSelectorLabel: "Sample Type", + parameters: new ParameterUIDescriptor[] { + new ParameterUIDescriptor( + name: "Texture", + tooltip: "The texture asset to sample" + ), + new ParameterUIDescriptor( + name: "Sampler", + tooltip: "The texture sampler to use for sampling the texture" + ), + new ParameterUIDescriptor( + name: "UV0", + tooltip: "The virtual UV for the base frame" + ), + new ParameterUIDescriptor( + name: "UV1", + tooltip: "The virtual UV for the second frame" + ), + new ParameterUIDescriptor( + name: "UV2", + tooltip: "The virtual UV for the third frame" + ), + new ParameterUIDescriptor( + name: "Grid", + tooltip: "The current UV grid" + ), + new ParameterUIDescriptor( + name: "Frames", + tooltip: "The amount of the imposter frames" + ), + new ParameterUIDescriptor( + name: "Clip", + tooltip: "The amount of clipping for a single frame" + ), + new ParameterUIDescriptor( + name: "Parallax", + tooltip: "Adds parallax effect the port value is true" + ), + new ParameterUIDescriptor( + name: "HeightMapChannel", + displayName:"Heigh Map Channel", + tooltip: "The texture channel to sample from for the parallax effect" + ), + new ParameterUIDescriptor( + name: "RGBA", + tooltip: "A vector4 from the sampled texture" + ) + } + ); + } +} diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs.meta new file mode 100644 index 00000000000..8a706bbb5be --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a6f1bf7c54fba824fb10c73483a88e77 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs new file mode 100644 index 00000000000..781fbbc94f3 --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs @@ -0,0 +1,124 @@ +using UnityEditor.ShaderGraph.GraphDelta; +using Usage = UnityEditor.ShaderGraph.GraphDelta.GraphType.Usage; + +namespace UnityEditor.ShaderGraph.Defs +{ + internal class ImposterUVNode : IStandardNode + { + static string Name => "ImposterUVNode"; + static int Version => 1; + public static NodeDescriptor NodeDescriptor => new( + Version, + Name, + "ImposteUV", + functions: new FunctionDescriptor[] { + new( + "ThreeFrames", +" ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, OutPos, Grid, UV0, UV1, UV2);", + new ParameterDescriptor[] + { + new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), + new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), + new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), + new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), + new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), + new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), + new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("UV0", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("UV1", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("UV2", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) + }, + new string[] + { + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" + } + ),new( + "OneFrame", +" ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, HemiSphere, OutPos, Grid, UV0);", + new ParameterDescriptor[] + { + new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), + new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), + new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), + new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), + new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1f}), + new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), + new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("UV0", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) + }, + new string[] + { + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" + } + ) + } + ); + + public static NodeUIDescriptor NodeUIDescriptor => new( + Version, + Name, + displayName: "Imposter UV", + tooltip: "Calculates the billboard positon and the virtual UVs for sampling.", + category: "Input/Mesh Deformation", + hasPreview: false, + description: "pkg://Documentation~/previews/ImposterUV.md", + synonyms: new string[] { "billboard" }, + selectableFunctions: new() + { + { "ThreeFrames", "Three Frames" }, + { "OneFrame", "One Frame" } + }, + functionSelectorLabel: "Sample Type", + parameters: new ParameterUIDescriptor[] { + new ParameterUIDescriptor( + name: "Pos", + displayName:"In Position", + tooltip: "The postiont in Object space" + ), + new ParameterUIDescriptor( + name: "UV", + tooltip: "The UV coordinates of the mesh" + ), + new ParameterUIDescriptor( + name: "Frames", + tooltip: "The amount of the imposter frames" + ), + new ParameterUIDescriptor( + name: "Offest", + tooltip: "The offset value from the origin vertex positon" + ), + new ParameterUIDescriptor( + name: "Size", + tooltip: "The size of the imposter" + ), + new ParameterUIDescriptor( + name: "HemiSphere", + tooltip: "If it's true, calculate imposter grid and UVs base on hemisphere type." + ), + new ParameterUIDescriptor( + name: "OutPos", + displayName:"Out Position", + tooltip: "The output billboard position." + ), + new ParameterUIDescriptor( + name: "UV0", + tooltip: "The virtual UV for the base frame" + ), + new ParameterUIDescriptor( + name: "UV1", + tooltip: "The virtual UV for the second frame" + ), + new ParameterUIDescriptor( + name: "UV2", + tooltip: "The virtual UV for the third frame" + ), + new ParameterUIDescriptor( + name: "Grid", + tooltip: "The current UV grid" + ) + } + ); + } +} diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs.meta new file mode 100644 index 00000000000..f89ec0d890f --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 983c760811aff784b9ceb86980c5eb57 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From dba3cd2e8fc0d4aef7ee00eed24158578cccfdf0 Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Mon, 17 Apr 2023 14:44:47 -0700 Subject: [PATCH 02/20] sg1 imposter nodes --- .../MeshDeformation/ImposterSampleNode.cs | 155 +++++++ .../ImposterSampleNode.cs.meta | 11 + .../Nodes/MeshDeformation/ImposterUVNode.cs | 123 ++++++ .../MeshDeformation/ImposterUVNode.cs.meta | 11 + .../ShaderGraphLibrary/Imposter.hlsl | 410 ++++++++++++++++++ .../ShaderGraphLibrary/Imposter.hlsl.meta | 7 + 6 files changed, 717 insertions(+) create mode 100644 com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs create mode 100644 com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs.meta create mode 100644 com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs create mode 100644 com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs.meta create mode 100644 com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl create mode 100644 com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl.meta diff --git a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs new file mode 100644 index 00000000000..1ff7d1fed9e --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs @@ -0,0 +1,155 @@ +using UnityEngine; +using UnityEditor.Graphing; +using UnityEditor.ShaderGraph.Internal; +using UnityEditor.ShaderGraph.Drawing.Controls; + + +namespace UnityEditor.ShaderGraph +{ + enum SampleType + { + OneFrame, + ThreeFrame + }; + + [Title("Input", "Mesh Deformation", "ImposterSample")] + class ImposterSampleNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireTransform, IMayRequirePosition, IMayRequireNormal, IMayRequireTangent, IGeneratesFunction, IMayRequireViewDirection + { + private const int RGBAOutputSlotId = 0; + + private const int SamplerSlotId = 1; + private const int UV0SlotId = 2; + private const int UV1SlotId = 3; + private const int UV2SlotId = 4; + private const int ImposterFramesSlotId = 6; + private const int TextureSlotId = 5; + private const int ParallaxCheckSlotId = 7; + private const int ImposterBorderClampSlotId = 8; + private const int UVGridSlotId = 9; + private const int ViewDirSlotId = 10; + private const int HeightMapChannelSlotId = 11; + + public const string kRGBAOutputSlotName = "RGBA"; + + public const string kSlotSamplerName = "Sampler State"; + public const string kUV0SlotName = "UV0"; + public const string kUV1SlotName = "UV1"; + public const string kUV2SlotName = "UV2"; + public const string kImposterFramesName = "Imposter Frames"; + public const string kSlotTextureName = "Texture"; + public const string kParallaxCheckName = "Parallax"; + public const string kImposterBorderClampName = "Imposter Clip"; + public const string kUVGridName = "UVGrid"; + public const string kViewDirName = "View Dir"; + public const string kHeightMapChannelName = "Height Map Channel"; + + + public ImposterSampleNode() + { + name = "ImposterSample"; + precision = Precision.Single; + synonyms = new string[] { "" }; + UpdateNodeAfterDeserialization(); + } + + + [SerializeField] + private SampleType m_SampleType = SampleType.ThreeFrame; + + [EnumControl("Sample Type")] + public SampleType sampleType + { + get { return m_SampleType; } + set + { + if (m_SampleType == value) + return; + + m_SampleType = value; + Dirty(ModificationScope.Graph); + + ValidateNode(); + } + } + + public sealed override void UpdateNodeAfterDeserialization() + { + AddSlot(new Vector4MaterialSlot(RGBAOutputSlotId, kRGBAOutputSlotName, kRGBAOutputSlotName, SlotType.Output, Vector4.zero)); + + AddSlot(new Texture2DInputMaterialSlot(TextureSlotId, kSlotTextureName, kSlotTextureName)); + AddSlot(new SamplerStateMaterialSlot(SamplerSlotId, kSlotSamplerName, kSlotSamplerName, SlotType.Input)); + AddSlot(new Vector4MaterialSlot(UV0SlotId, kUV0SlotName, kUV0SlotName, SlotType.Input, Vector4.zero)); + AddSlot(new Vector4MaterialSlot(UV1SlotId, kUV1SlotName, kUV1SlotName, SlotType.Input, Vector4.zero)); + AddSlot(new Vector4MaterialSlot(UV2SlotId, kUV2SlotName, kUV2SlotName, SlotType.Input, Vector4.zero)); + AddSlot(new Vector4MaterialSlot(UVGridSlotId, kUVGridName, kUVGridName, SlotType.Input, Vector4.zero)); + AddSlot(new Vector1MaterialSlot(ImposterFramesSlotId, kImposterFramesName, kImposterFramesName, SlotType.Input, 16)); + AddSlot(new Vector1MaterialSlot(ImposterBorderClampSlotId, kImposterBorderClampName, kImposterBorderClampName, SlotType.Input, 1)); + AddSlot(new Vector1MaterialSlot(ParallaxCheckSlotId, kParallaxCheckName, kParallaxCheckName, SlotType.Input, 0)); + AddSlot(new Vector1MaterialSlot(HeightMapChannelSlotId, kHeightMapChannelName, kHeightMapChannelName, SlotType.Input, 3)); + AddSlot(new ViewDirectionMaterialSlot(ViewDirSlotId, kViewDirName, kViewDirName, CoordinateSpace.Tangent)); + + + RemoveSlotsNameNotMatching(new[] { HeightMapChannelSlotId, ViewDirSlotId, ParallaxCheckSlotId, RGBAOutputSlotId, TextureSlotId, SamplerSlotId, UV0SlotId, UV1SlotId, UV2SlotId, ImposterFramesSlotId, ImposterBorderClampSlotId, UVGridSlotId }); + } + public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode) + { + registry.RequiresIncludePath("Packages/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl"); + } + public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode) + { + var RGBA = GetVariableNameForSlot(RGBAOutputSlotId); + var ImposterFrames = GetSlotValue(ImposterFramesSlotId, generationMode); + var UV0 = GetSlotValue(UV0SlotId, generationMode); + var UV1 = GetSlotValue(UV1SlotId, generationMode); + var UV2 = GetSlotValue(UV2SlotId, generationMode); + var Texture = GetSlotValue(TextureSlotId, generationMode); + var ss = GetSlotValue(SamplerSlotId, generationMode); + var BorderClamp = GetSlotValue(ImposterBorderClampSlotId, generationMode); + var UVGrid = GetSlotValue(UVGridSlotId, generationMode); + var parallax = GetSlotValue(ParallaxCheckSlotId, generationMode); + var viewDir = GetSlotValue(ViewDirSlotId, generationMode); + var channel = GetSlotValue(HeightMapChannelSlotId, generationMode); + + var result = @$"$precision4 {RGBA};"; + if (m_SampleType == SampleType.ThreeFrame) + { + result += $@"ImposterSample({channel},{viewDir}, {parallax}, {ImposterFrames}, {Texture}.tex, {Texture}.texelSize, {BorderClamp}, + {UVGrid}, {UV0}, {UV1}, {UV2}, {ss}.samplerstate, {RGBA});"; + } + else + { + result += $@"ImposterSample_oneFrame({channel},{viewDir},{parallax}, {ImposterFrames}, {Texture}.tex, {Texture}.texelSize, {BorderClamp}, + {UVGrid}, {UV0}, {ss}.samplerstate, {RGBA});"; + } + + sb.AppendLine(result); + } + public NeededTransform[] RequiresTransform(ShaderStageCapability stageCapability = ShaderStageCapability.All) => new[] { NeededTransform.ObjectToWorld }; + public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All) + { + if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) + return NeededCoordinateSpace.Object; + else + return NeededCoordinateSpace.None; + } + public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability = ShaderStageCapability.All) + { + if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) + return NeededCoordinateSpace.Object; + else + return NeededCoordinateSpace.None; + } + public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability = ShaderStageCapability.All) + { + return NeededCoordinateSpace.Tangent; + } + public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability = ShaderStageCapability.All) + { + if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) + return NeededCoordinateSpace.Object; + else + return NeededCoordinateSpace.None; + } + } + +} diff --git a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs.meta b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs.meta new file mode 100644 index 00000000000..66fbfc57644 --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b1152b5cb8b624a48aaefa26cf3cd7ba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs new file mode 100644 index 00000000000..ece29d85bc8 --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs @@ -0,0 +1,123 @@ +using UnityEngine; +using UnityEditor.Graphing; +using UnityEditor.ShaderGraph.Internal; +using UnityEditor.ShaderGraph.Drawing.Controls; + + +namespace UnityEditor.ShaderGraph +{ + [Title("Input", "Mesh Deformation", "ImposterUV")] + class ImposterUVNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireTransform, IMayRequirePosition, IMayRequireNormal, IMayRequireTangent, IGeneratesFunction + { + private const int UV0OutputSlotId = 0; + private const int UV1OutputSlotId = 1; + private const int UV2OutputSlotId = 2; + private const int ImposterPosOutputSlotId = 3; + private const int UVGridOutputSlotId = 4; + + private const int PositionInputSlotId = 5; + private const int UVInputSlotId = 6; + private const int ImposterFramesInputSlotId = 7; + private const int ImposterOffsetInputSlotId = 8; + private const int ImposterSizeInputSlotId = 9; + private const int ImposterHemiCheckInputSlotId = 10; + + public const string kUV0OutputSlotName = "UV0"; + public const string kUV1OutputSlotName = "UV1"; + public const string kUV2OutputSlotName = "UV2"; + public const string kImposterPosOutputSlotName = "Imposter Position"; + public const string kUVGridOutputSlotName = "UV Grid"; + + public const string kPositionInputSlotName = "Position"; + public const string kUVInputSlotName = "UV"; + public const string kImposterFramesInputSlotName = "Imposter Frames"; + public const string kImposterOffsetInputSlotName = "Imposter Offset"; + public const string kImposterSizeInputSlotName = "Imposter Size"; + public const string kImposterHemiCheckInputSlotName = "Hemi Sphere"; + + + public ImposterUVNode() + { + name = "ImposterUV"; + precision = Precision.Single; + synonyms = new string[] { "" }; + UpdateNodeAfterDeserialization(); + } + + public sealed override void UpdateNodeAfterDeserialization() + { + AddSlot(new Vector3MaterialSlot(ImposterPosOutputSlotId, kImposterPosOutputSlotName, kImposterPosOutputSlotName, SlotType.Output, Vector3.zero)); + AddSlot(new Vector4MaterialSlot(UV0OutputSlotId, kUV0OutputSlotName, kUV0OutputSlotName, SlotType.Output, Vector4.zero)); + AddSlot(new Vector4MaterialSlot(UV1OutputSlotId, kUV1OutputSlotName, kUV1OutputSlotName, SlotType.Output, Vector4.zero)); + AddSlot(new Vector4MaterialSlot(UV2OutputSlotId, kUV2OutputSlotName, kUV2OutputSlotName, SlotType.Output, Vector4.zero)); + AddSlot(new Vector4MaterialSlot(UVGridOutputSlotId, kUVGridOutputSlotName, kUVGridOutputSlotName, SlotType.Output, Vector4.zero)); + + AddSlot(new Vector3MaterialSlot(PositionInputSlotId, kPositionInputSlotName, kPositionInputSlotName, SlotType.Input, Vector3.zero)); + AddSlot(new Vector4MaterialSlot(UVInputSlotId, kUVInputSlotName, kUVInputSlotName, SlotType.Input, Vector4.zero)); + AddSlot(new Vector1MaterialSlot(ImposterFramesInputSlotId, kImposterFramesInputSlotName, kImposterFramesInputSlotName, SlotType.Input, 16)); + AddSlot(new Vector3MaterialSlot(ImposterOffsetInputSlotId, kImposterOffsetInputSlotName, kImposterOffsetInputSlotName, SlotType.Input, Vector3.zero)); + AddSlot(new Vector1MaterialSlot(ImposterSizeInputSlotId, kImposterSizeInputSlotName, kImposterSizeInputSlotName, SlotType.Input, 1)); + AddSlot(new BooleanMaterialSlot(ImposterHemiCheckInputSlotId, kImposterHemiCheckInputSlotName, kImposterHemiCheckInputSlotName, SlotType.Input, false)); + + RemoveSlotsNameNotMatching(new[] { ImposterHemiCheckInputSlotId, ImposterPosOutputSlotId, UV0OutputSlotId, UV1OutputSlotId, UV2OutputSlotId, UVGridOutputSlotId, PositionInputSlotId, UVInputSlotId, ImposterFramesInputSlotId, ImposterOffsetInputSlotId, ImposterSizeInputSlotId }); + } + public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode) + { + registry.RequiresIncludePath("Packages/com.unity.shadergraph/ShaderGraphLibrary/Imposter_2Nodes.hlsl"); + } + public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode) + { + var UV0 = GetVariableNameForSlot(UV0OutputSlotId); + var UV1 = GetVariableNameForSlot(UV1OutputSlotId); + var UV2 = GetVariableNameForSlot(UV2OutputSlotId); + var outPos = GetVariableNameForSlot(ImposterPosOutputSlotId); + var outUVGrid = GetVariableNameForSlot(UVGridOutputSlotId); + + var inPos = GetSlotValue(PositionInputSlotId, generationMode); + var inUV = GetSlotValue(UVInputSlotId, generationMode); + var imposterFrame = GetSlotValue(ImposterFramesInputSlotId, generationMode); + var imposterOffset = GetSlotValue(ImposterOffsetInputSlotId, generationMode); + var imposterSize = GetSlotValue(ImposterSizeInputSlotId, generationMode); + var hemiCheck = GetSlotValue(ImposterHemiCheckInputSlotId, generationMode); + + var result = @$" +$precision4 {UV0}; +$precision4 {UV1}; +$precision4 {UV2}; +$precision3 {outPos}; +$precision4 {outUVGrid}; +"; + + + //TODO: change it to call ImposterUV_Parallax + result += $@"ImposterUV({inPos}, {inUV}, {imposterFrame}, {imposterOffset}, {imposterSize}, {hemiCheck}, + {outPos}, {outUVGrid}, {UV0}, {UV1}, {UV2});"; + + sb.AppendLine(result); + } + public NeededTransform[] RequiresTransform(ShaderStageCapability stageCapability = ShaderStageCapability.All) => new[] { NeededTransform.ObjectToWorld }; + public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All) + { + if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) + return NeededCoordinateSpace.Object; + else + return NeededCoordinateSpace.None; + } + public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability = ShaderStageCapability.All) + { + if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) + return NeededCoordinateSpace.Object; + else + return NeededCoordinateSpace.None; + } + + public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability = ShaderStageCapability.All) + { + if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) + return NeededCoordinateSpace.Object; + else + return NeededCoordinateSpace.None; + } + } + +} diff --git a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs.meta b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs.meta new file mode 100644 index 00000000000..dd25f585e14 --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 92a02af6d9f25484fba502d43a2b363c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl b/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl new file mode 100644 index 00000000000..66e3fd20cf2 --- /dev/null +++ b/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl @@ -0,0 +1,410 @@ +#ifndef IMPOSTERSTART +#define IMPOSTESTART + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Sampling.hlsl" +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ParallaxMapping.hlsl" + +struct Ray +{ + float3 Origin; + float3 Direction; +}; + +float3 CoordToHemi(float2 coord) +{ + coord = float2(coord.x + coord.y, coord.x - coord.y) * 0.5; + float3 dir = float3(coord.x, 1 - dot(float2(1, 1), abs(coord.xy)), coord.y); + return dir; +} + +float3 CoordToOcta(float2 coord) +{ + float3 dir = float3(coord.x, 1 - dot(1, abs(coord)), coord.y); + if (dir.y < 0) + { + float2 flip = dir.xz >= 0 ? float2(1, 1) : float2(-1, -1); + dir.xz = (1 - abs(dir.zx)) * flip; + } + return dir; +} + +float3 GridToVector(float2 coord, bool IsHemi) +{ + float3 dir; + if (IsHemi) + { + dir = CoordToHemi(coord); + } + else + { + dir = CoordToOcta(coord); + } + return dir; +} + +//for hemisphere +float2 VectorToHemi(float3 dir) +{ + dir.xz /= dot(1.0, abs(dir)); + return float2(dir.x + dir.z, dir.x - dir.z); +} + +float2 VectorToOcta(float3 dir) +{ + dir.xz /= dot(1, abs(dir)); + if (dir.y <= 0) + { + dir.xz = (1 - abs(dir.zx)) * (dir.xz >= 0 ? 1.0 : -1.0); + } + return dir.xz; +} + +//weights base on the triangle +float4 CalculateWeights(float2 uv) +{ + uv = frac(uv); + + float2 oneMinusUV = 1 - uv.xy; + + float4 res; + //frame 0 + res.x = min(oneMinusUV.x, oneMinusUV.y); + //frame 1 + res.y = abs(dot(uv, float2(1.0, -1.0))); + //frame 2 + res.z = min(uv.x, uv.y); + //mask + res.w = saturate(ceil(uv.x - uv.y)); + + return res; +} + +float3 FrameTransformLocal(float3 BillboardPosToCam, float3 normal, out float3 worldX, out float3 worldZ) +{ + float3 upVector = float3 (0, 1, 0); + worldX = normalize(cross(upVector, normal)); + worldZ = normalize(cross(worldX, normal)); + + BillboardPosToCam *= -1.0; + + float3x3 worldToLocal = float3x3(worldX, worldZ, normal); + float3 localRay = normalize(mul(worldToLocal, BillboardPosToCam)); + return localRay; +} + +float2 PlaneIntersectionUV(float3 planeNormal, float3 planeX, float3 planeZ, float3 center, float2 UVscale, Ray ray) +{ + float normalDotOrigin = dot(planeNormal, -ray.Origin);//(p0 - l0) . n + float normalDotRay = dot(planeNormal, ray.Direction);//l.n + float planeDistance = normalDotOrigin / normalDotRay;//distance >0 then intersecting + + //intersect = rayDir * distance + rayPos + float3 intersection = ((ray.Direction * planeDistance) + ray.Origin) - center; + + float dx = dot(planeX, intersection); + float dz = dot(planeZ, intersection); + + float2 uv = float2(0, 0); + + if (planeDistance > 0) + { + uv = -float2(dx, dz); + } + else + { + uv = float2(0, 0); + } + + uv /= UVscale; + uv += float2(0.5, 0.5); + return uv; +} + +float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) +{ + float3 up = normalize(objectSpaceCameraDir); + float3 x = normalize(cross(up, float3(0.0, 1.0, 0.0))); + float3 z = normalize(cross(x, up)); + + uv = uv * 2.0 - 1.0; + + float3 newX = x * uv.x; + float3 newZ = z * uv.y; + + float3 result = newX + newZ; + + return result; +} + +//Calculate Vertex postion and UVs +void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, + out float3 outPos, out float4 outUVGrid, out float4 outUV0, out float4 outUV1, out float4 outUV2) +{ + float framesMinusOne = imposterFrames - 1; + + //camera pos in object space + float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz; + float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); + + //get uv in a single frame + float2 UVscaled = inUV.xy * (1.0 / imposterFrames); + float2 size = imposterSize.xx * 2.0; + + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + + //camera to projection vector + float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; + + //BillboardPos position to camera ray + float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); + + Ray ray; + ray.Origin = objectSpaceCameraPos; + ray.Direction = rayDirLocal; + + //set up virtual grid + float2 grid; + if (isHemi) { + objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); + grid = VectorToHemi(objectSpaceCameraDir); + } + else { + grid = VectorToOcta(objectSpaceCameraDir); + } + + grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 + grid *= framesMinusOne;//multiply framesMinusOne to cover the texture + + float2 gridFrac = frac(grid); + float2 gridFloor = floor(grid); + + float4 weights = CalculateWeights(gridFrac); + + //set up for octahedron: + //1.find the nearest 3 frames + //2.base on the grid find the direction intersect with the octahedron + //3.construct the face/plane for that direction + //4.base on the plane and find the virtual uv coord + + //get the 3 nearest frames + float2 frame0 = gridFloor; + float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); + float2 frame2 = gridFloor + float2(1, 1); + + //convert frame coordinate to octahedron direction + float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); + float3 frame1ray = normalize(GridToVector(float2(frame1 / framesMinusOne * 2 - 1), isHemi)); + float3 frame2ray = normalize(GridToVector(float2(frame2 / framesMinusOne * 2 - 1), isHemi)); + + float3 center = float3(0, 0, 0); + + float3 plane0x; + float3 plane0normal = frame0ray; + float3 plane0z; + float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); + + float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); + vUv0 /= imposterFrames; + + float3 plane1x; + float3 plane1normal = frame1ray; + float3 plane1z; + float3 frame1local = FrameTransformLocal(BillboardPosToCam, frame1ray, plane1x, plane1z); + + float2 vUv1 = PlaneIntersectionUV(plane1normal, plane1x, plane1z, center, size, ray); + vUv1 /= imposterFrames; + + float3 plane2x; + float3 plane2normal = frame2ray; + float3 plane2z; + float3 frame2local = FrameTransformLocal(BillboardPosToCam, frame2ray, plane2x, plane2z); + + float2 vUv2 = PlaneIntersectionUV(plane2normal, plane2x, plane2z, center, size, ray); + vUv2 /= imposterFrames; + + frame0local.xy /= imposterFrames; + frame1local.xy /= imposterFrames; + frame2local.xy /= imposterFrames; + + //vert pos + outPos = BillboardPos + imposterOffset; + + //surface + outUVGrid.xy = UVscaled; + outUVGrid.zw = grid; + outUV0 = float4(vUv0.xy, frame0local.xz); + outUV1 = float4(vUv1.xy, frame1local.xz); + outUV2 = float4(vUv2.xy, frame2local.xz);; +} +void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, + out float3 outPos, out float4 outUVGrid, out float4 outUV0) +{ + float framesMinusOne = imposterFrames - 1; + + //camera pos in object space + float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz; + float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); + + //get uv in a single frame + float2 UVscaled = inUV.xy * (1.0 / imposterFrames); + float2 size = imposterSize.xx * 2.0; + + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + + //camera to projection vector + float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; + + //BillboardPos position to camera ray + float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); + + Ray ray; + ray.Origin = objectSpaceCameraPos; + ray.Direction = rayDirLocal; + + //set up virtual grid + float2 grid; + if (isHemi) { + objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); + grid = VectorToHemi(objectSpaceCameraDir); + } + else { + grid = VectorToOcta(objectSpaceCameraDir); + } + + grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 + grid *= framesMinusOne;//multiply framesMinusOne to cover the texture + + float2 gridFrac = frac(grid); + float2 gridFloor = floor(grid); + + float4 weights = CalculateWeights(gridFrac); + + //set up for octahedron: + //1.find the nearest 3 frames + //2.base on the grid find the direction intersect with the octahedron + //3.construct the face/plane for that direction + //4.base on the plane and find the virtual uv coord + + //get the 3 nearest frames + float2 frame0 = gridFloor; + float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); + float2 frame2 = gridFloor + float2(1, 1); + + //convert frame coordinate to octahedron direction + float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); + + float3 center = float3(0, 0, 0); + + float3 plane0x; + float3 plane0normal = frame0ray; + float3 plane0z; + float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); + + float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); + vUv0 /= imposterFrames; + + frame0local.xy /= imposterFrames; + + //vert pos + outPos = BillboardPos + imposterOffset; + + //surface + outUVGrid.xy = UVscaled; + outUVGrid.zw = grid; + outUV0 = float4(vUv0.xy, frame0local.xz); + +} +//Sample from UVs +void ImposterSample(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, + in float imposterClip, in float4 inUVGrid, in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) +{ + float2 inUV = inUVGrid.xy; + + float2 fracGrid = frac(inUVGrid.zw); + + float4 weights = CalculateWeights(fracGrid); + + float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; + + float2 frame0 = gridSnap; + float2 frame1 = gridSnap + (lerp(float2(0, 1), float2(1, 0), weights.w) / imposterFrames.xx); + float2 frame2 = gridSnap + (float2(1, 1) / imposterFrames.xx); + + float2 vp0uv = frame0 + inUV0.xy; + float2 vp1uv = frame1 + inUV1.xy; + float2 vp2uv = frame2 + inUV2.xy; + + //frame size ->2048/12 = 170.6 + float frameSize = mapTexelSize.z / imposterFrames; + //actual texture size used -> 170*12 = 2040 + float actualTextureSize = floor(frameSize) * imposterFrames; + //the scalar -> 2048/2040 = 0.99609375 + float scalar = mapTexelSize.z / actualTextureSize; + + vp0uv *= scalar; + vp1uv *= scalar; + vp2uv *= scalar; + + if (parallax != 0) { + + vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + vp1uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); + vp2uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); + } + + // clip out neighboring frames + float2 gridSize = 1.0 / imposterFrames.xx; + float2 bleeds = mapTexelSize.xy * imposterClip; + vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); + vp1uv = clamp(vp1uv, frame1 - bleeds, frame1 + gridSize + bleeds); + vp2uv = clamp(vp2uv, frame2 - bleeds, frame2 + gridSize + bleeds); + + float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)) * weights.x + + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp1uv, ddx(inUV), ddy(inUV)) * weights.y + + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp2uv, ddx(inUV), ddy(inUV)) * weights.z; + + outColor.a = blendedColor.a - imposterClip + 1; + clip(outColor.a); + outColor.rgb = blendedColor.rgb; +} + +void ImposterSample_oneFrame(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, + in float imposterClip, in float4 inUVGrid, in float4 inUV0, in SamplerState ss, out float4 outColor) +{ + float2 inUV = inUVGrid.xy; + + float2 fracGrid = frac(inUVGrid.zw); + + float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; + + float2 frame0 = gridSnap; + + float2 vp0uv = frame0 + inUV0.xy; + + //frame size ->2048/12 = 170.6 + float frameSize = mapTexelSize.z / imposterFrames; + //actual texture size used -> 170*12 = 2040 + float actualTextureSize = floor(frameSize) * imposterFrames; + //the scalar -> 2048/2040 = 0.99609375 + float scalar = mapTexelSize.z / actualTextureSize; + + vp0uv *= scalar; + + if (parallax != 0) { + + vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + } + + // clip out neighboring frames + float2 gridSize = 1.0 / imposterFrames.xx; + float2 bleeds = mapTexelSize.xy * imposterClip; + vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); + + float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)); + + outColor.a = blendedColor.a - imposterClip + 1; + clip(outColor.a); + outColor.rgb = blendedColor.rgb; +} + +#endif diff --git a/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl.meta b/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl.meta new file mode 100644 index 00000000000..30f6948528a --- /dev/null +++ b/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d79c6812a6dfb2d4c92954b2620142fe +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From a38c6957bc8f4e6598482c752206a81d29d14009 Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Mon, 17 Apr 2023 14:49:20 -0700 Subject: [PATCH 03/20] Revert "sg1 imposter nodes" This reverts commit dba3cd2e8fc0d4aef7ee00eed24158578cccfdf0. --- .../MeshDeformation/ImposterSampleNode.cs | 155 ------- .../ImposterSampleNode.cs.meta | 11 - .../Nodes/MeshDeformation/ImposterUVNode.cs | 123 ------ .../MeshDeformation/ImposterUVNode.cs.meta | 11 - .../ShaderGraphLibrary/Imposter.hlsl | 410 ------------------ .../ShaderGraphLibrary/Imposter.hlsl.meta | 7 - 6 files changed, 717 deletions(-) delete mode 100644 com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs delete mode 100644 com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs.meta delete mode 100644 com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs delete mode 100644 com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs.meta delete mode 100644 com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl delete mode 100644 com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl.meta diff --git a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs deleted file mode 100644 index 1ff7d1fed9e..00000000000 --- a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs +++ /dev/null @@ -1,155 +0,0 @@ -using UnityEngine; -using UnityEditor.Graphing; -using UnityEditor.ShaderGraph.Internal; -using UnityEditor.ShaderGraph.Drawing.Controls; - - -namespace UnityEditor.ShaderGraph -{ - enum SampleType - { - OneFrame, - ThreeFrame - }; - - [Title("Input", "Mesh Deformation", "ImposterSample")] - class ImposterSampleNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireTransform, IMayRequirePosition, IMayRequireNormal, IMayRequireTangent, IGeneratesFunction, IMayRequireViewDirection - { - private const int RGBAOutputSlotId = 0; - - private const int SamplerSlotId = 1; - private const int UV0SlotId = 2; - private const int UV1SlotId = 3; - private const int UV2SlotId = 4; - private const int ImposterFramesSlotId = 6; - private const int TextureSlotId = 5; - private const int ParallaxCheckSlotId = 7; - private const int ImposterBorderClampSlotId = 8; - private const int UVGridSlotId = 9; - private const int ViewDirSlotId = 10; - private const int HeightMapChannelSlotId = 11; - - public const string kRGBAOutputSlotName = "RGBA"; - - public const string kSlotSamplerName = "Sampler State"; - public const string kUV0SlotName = "UV0"; - public const string kUV1SlotName = "UV1"; - public const string kUV2SlotName = "UV2"; - public const string kImposterFramesName = "Imposter Frames"; - public const string kSlotTextureName = "Texture"; - public const string kParallaxCheckName = "Parallax"; - public const string kImposterBorderClampName = "Imposter Clip"; - public const string kUVGridName = "UVGrid"; - public const string kViewDirName = "View Dir"; - public const string kHeightMapChannelName = "Height Map Channel"; - - - public ImposterSampleNode() - { - name = "ImposterSample"; - precision = Precision.Single; - synonyms = new string[] { "" }; - UpdateNodeAfterDeserialization(); - } - - - [SerializeField] - private SampleType m_SampleType = SampleType.ThreeFrame; - - [EnumControl("Sample Type")] - public SampleType sampleType - { - get { return m_SampleType; } - set - { - if (m_SampleType == value) - return; - - m_SampleType = value; - Dirty(ModificationScope.Graph); - - ValidateNode(); - } - } - - public sealed override void UpdateNodeAfterDeserialization() - { - AddSlot(new Vector4MaterialSlot(RGBAOutputSlotId, kRGBAOutputSlotName, kRGBAOutputSlotName, SlotType.Output, Vector4.zero)); - - AddSlot(new Texture2DInputMaterialSlot(TextureSlotId, kSlotTextureName, kSlotTextureName)); - AddSlot(new SamplerStateMaterialSlot(SamplerSlotId, kSlotSamplerName, kSlotSamplerName, SlotType.Input)); - AddSlot(new Vector4MaterialSlot(UV0SlotId, kUV0SlotName, kUV0SlotName, SlotType.Input, Vector4.zero)); - AddSlot(new Vector4MaterialSlot(UV1SlotId, kUV1SlotName, kUV1SlotName, SlotType.Input, Vector4.zero)); - AddSlot(new Vector4MaterialSlot(UV2SlotId, kUV2SlotName, kUV2SlotName, SlotType.Input, Vector4.zero)); - AddSlot(new Vector4MaterialSlot(UVGridSlotId, kUVGridName, kUVGridName, SlotType.Input, Vector4.zero)); - AddSlot(new Vector1MaterialSlot(ImposterFramesSlotId, kImposterFramesName, kImposterFramesName, SlotType.Input, 16)); - AddSlot(new Vector1MaterialSlot(ImposterBorderClampSlotId, kImposterBorderClampName, kImposterBorderClampName, SlotType.Input, 1)); - AddSlot(new Vector1MaterialSlot(ParallaxCheckSlotId, kParallaxCheckName, kParallaxCheckName, SlotType.Input, 0)); - AddSlot(new Vector1MaterialSlot(HeightMapChannelSlotId, kHeightMapChannelName, kHeightMapChannelName, SlotType.Input, 3)); - AddSlot(new ViewDirectionMaterialSlot(ViewDirSlotId, kViewDirName, kViewDirName, CoordinateSpace.Tangent)); - - - RemoveSlotsNameNotMatching(new[] { HeightMapChannelSlotId, ViewDirSlotId, ParallaxCheckSlotId, RGBAOutputSlotId, TextureSlotId, SamplerSlotId, UV0SlotId, UV1SlotId, UV2SlotId, ImposterFramesSlotId, ImposterBorderClampSlotId, UVGridSlotId }); - } - public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode) - { - registry.RequiresIncludePath("Packages/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl"); - } - public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode) - { - var RGBA = GetVariableNameForSlot(RGBAOutputSlotId); - var ImposterFrames = GetSlotValue(ImposterFramesSlotId, generationMode); - var UV0 = GetSlotValue(UV0SlotId, generationMode); - var UV1 = GetSlotValue(UV1SlotId, generationMode); - var UV2 = GetSlotValue(UV2SlotId, generationMode); - var Texture = GetSlotValue(TextureSlotId, generationMode); - var ss = GetSlotValue(SamplerSlotId, generationMode); - var BorderClamp = GetSlotValue(ImposterBorderClampSlotId, generationMode); - var UVGrid = GetSlotValue(UVGridSlotId, generationMode); - var parallax = GetSlotValue(ParallaxCheckSlotId, generationMode); - var viewDir = GetSlotValue(ViewDirSlotId, generationMode); - var channel = GetSlotValue(HeightMapChannelSlotId, generationMode); - - var result = @$"$precision4 {RGBA};"; - if (m_SampleType == SampleType.ThreeFrame) - { - result += $@"ImposterSample({channel},{viewDir}, {parallax}, {ImposterFrames}, {Texture}.tex, {Texture}.texelSize, {BorderClamp}, - {UVGrid}, {UV0}, {UV1}, {UV2}, {ss}.samplerstate, {RGBA});"; - } - else - { - result += $@"ImposterSample_oneFrame({channel},{viewDir},{parallax}, {ImposterFrames}, {Texture}.tex, {Texture}.texelSize, {BorderClamp}, - {UVGrid}, {UV0}, {ss}.samplerstate, {RGBA});"; - } - - sb.AppendLine(result); - } - public NeededTransform[] RequiresTransform(ShaderStageCapability stageCapability = ShaderStageCapability.All) => new[] { NeededTransform.ObjectToWorld }; - public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All) - { - if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) - return NeededCoordinateSpace.Object; - else - return NeededCoordinateSpace.None; - } - public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability = ShaderStageCapability.All) - { - if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) - return NeededCoordinateSpace.Object; - else - return NeededCoordinateSpace.None; - } - public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability = ShaderStageCapability.All) - { - return NeededCoordinateSpace.Tangent; - } - public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability = ShaderStageCapability.All) - { - if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) - return NeededCoordinateSpace.Object; - else - return NeededCoordinateSpace.None; - } - } - -} diff --git a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs.meta b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs.meta deleted file mode 100644 index 66fbfc57644..00000000000 --- a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterSampleNode.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b1152b5cb8b624a48aaefa26cf3cd7ba -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs deleted file mode 100644 index ece29d85bc8..00000000000 --- a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs +++ /dev/null @@ -1,123 +0,0 @@ -using UnityEngine; -using UnityEditor.Graphing; -using UnityEditor.ShaderGraph.Internal; -using UnityEditor.ShaderGraph.Drawing.Controls; - - -namespace UnityEditor.ShaderGraph -{ - [Title("Input", "Mesh Deformation", "ImposterUV")] - class ImposterUVNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireTransform, IMayRequirePosition, IMayRequireNormal, IMayRequireTangent, IGeneratesFunction - { - private const int UV0OutputSlotId = 0; - private const int UV1OutputSlotId = 1; - private const int UV2OutputSlotId = 2; - private const int ImposterPosOutputSlotId = 3; - private const int UVGridOutputSlotId = 4; - - private const int PositionInputSlotId = 5; - private const int UVInputSlotId = 6; - private const int ImposterFramesInputSlotId = 7; - private const int ImposterOffsetInputSlotId = 8; - private const int ImposterSizeInputSlotId = 9; - private const int ImposterHemiCheckInputSlotId = 10; - - public const string kUV0OutputSlotName = "UV0"; - public const string kUV1OutputSlotName = "UV1"; - public const string kUV2OutputSlotName = "UV2"; - public const string kImposterPosOutputSlotName = "Imposter Position"; - public const string kUVGridOutputSlotName = "UV Grid"; - - public const string kPositionInputSlotName = "Position"; - public const string kUVInputSlotName = "UV"; - public const string kImposterFramesInputSlotName = "Imposter Frames"; - public const string kImposterOffsetInputSlotName = "Imposter Offset"; - public const string kImposterSizeInputSlotName = "Imposter Size"; - public const string kImposterHemiCheckInputSlotName = "Hemi Sphere"; - - - public ImposterUVNode() - { - name = "ImposterUV"; - precision = Precision.Single; - synonyms = new string[] { "" }; - UpdateNodeAfterDeserialization(); - } - - public sealed override void UpdateNodeAfterDeserialization() - { - AddSlot(new Vector3MaterialSlot(ImposterPosOutputSlotId, kImposterPosOutputSlotName, kImposterPosOutputSlotName, SlotType.Output, Vector3.zero)); - AddSlot(new Vector4MaterialSlot(UV0OutputSlotId, kUV0OutputSlotName, kUV0OutputSlotName, SlotType.Output, Vector4.zero)); - AddSlot(new Vector4MaterialSlot(UV1OutputSlotId, kUV1OutputSlotName, kUV1OutputSlotName, SlotType.Output, Vector4.zero)); - AddSlot(new Vector4MaterialSlot(UV2OutputSlotId, kUV2OutputSlotName, kUV2OutputSlotName, SlotType.Output, Vector4.zero)); - AddSlot(new Vector4MaterialSlot(UVGridOutputSlotId, kUVGridOutputSlotName, kUVGridOutputSlotName, SlotType.Output, Vector4.zero)); - - AddSlot(new Vector3MaterialSlot(PositionInputSlotId, kPositionInputSlotName, kPositionInputSlotName, SlotType.Input, Vector3.zero)); - AddSlot(new Vector4MaterialSlot(UVInputSlotId, kUVInputSlotName, kUVInputSlotName, SlotType.Input, Vector4.zero)); - AddSlot(new Vector1MaterialSlot(ImposterFramesInputSlotId, kImposterFramesInputSlotName, kImposterFramesInputSlotName, SlotType.Input, 16)); - AddSlot(new Vector3MaterialSlot(ImposterOffsetInputSlotId, kImposterOffsetInputSlotName, kImposterOffsetInputSlotName, SlotType.Input, Vector3.zero)); - AddSlot(new Vector1MaterialSlot(ImposterSizeInputSlotId, kImposterSizeInputSlotName, kImposterSizeInputSlotName, SlotType.Input, 1)); - AddSlot(new BooleanMaterialSlot(ImposterHemiCheckInputSlotId, kImposterHemiCheckInputSlotName, kImposterHemiCheckInputSlotName, SlotType.Input, false)); - - RemoveSlotsNameNotMatching(new[] { ImposterHemiCheckInputSlotId, ImposterPosOutputSlotId, UV0OutputSlotId, UV1OutputSlotId, UV2OutputSlotId, UVGridOutputSlotId, PositionInputSlotId, UVInputSlotId, ImposterFramesInputSlotId, ImposterOffsetInputSlotId, ImposterSizeInputSlotId }); - } - public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode) - { - registry.RequiresIncludePath("Packages/com.unity.shadergraph/ShaderGraphLibrary/Imposter_2Nodes.hlsl"); - } - public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode) - { - var UV0 = GetVariableNameForSlot(UV0OutputSlotId); - var UV1 = GetVariableNameForSlot(UV1OutputSlotId); - var UV2 = GetVariableNameForSlot(UV2OutputSlotId); - var outPos = GetVariableNameForSlot(ImposterPosOutputSlotId); - var outUVGrid = GetVariableNameForSlot(UVGridOutputSlotId); - - var inPos = GetSlotValue(PositionInputSlotId, generationMode); - var inUV = GetSlotValue(UVInputSlotId, generationMode); - var imposterFrame = GetSlotValue(ImposterFramesInputSlotId, generationMode); - var imposterOffset = GetSlotValue(ImposterOffsetInputSlotId, generationMode); - var imposterSize = GetSlotValue(ImposterSizeInputSlotId, generationMode); - var hemiCheck = GetSlotValue(ImposterHemiCheckInputSlotId, generationMode); - - var result = @$" -$precision4 {UV0}; -$precision4 {UV1}; -$precision4 {UV2}; -$precision3 {outPos}; -$precision4 {outUVGrid}; -"; - - - //TODO: change it to call ImposterUV_Parallax - result += $@"ImposterUV({inPos}, {inUV}, {imposterFrame}, {imposterOffset}, {imposterSize}, {hemiCheck}, - {outPos}, {outUVGrid}, {UV0}, {UV1}, {UV2});"; - - sb.AppendLine(result); - } - public NeededTransform[] RequiresTransform(ShaderStageCapability stageCapability = ShaderStageCapability.All) => new[] { NeededTransform.ObjectToWorld }; - public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All) - { - if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) - return NeededCoordinateSpace.Object; - else - return NeededCoordinateSpace.None; - } - public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability = ShaderStageCapability.All) - { - if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) - return NeededCoordinateSpace.Object; - else - return NeededCoordinateSpace.None; - } - - public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability = ShaderStageCapability.All) - { - if (stageCapability == ShaderStageCapability.Vertex || stageCapability == ShaderStageCapability.All) - return NeededCoordinateSpace.Object; - else - return NeededCoordinateSpace.None; - } - } - -} diff --git a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs.meta b/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs.meta deleted file mode 100644 index dd25f585e14..00000000000 --- a/com.unity.shadergraph/Editor/Data/Nodes/MeshDeformation/ImposterUVNode.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 92a02af6d9f25484fba502d43a2b363c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl b/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl deleted file mode 100644 index 66e3fd20cf2..00000000000 --- a/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl +++ /dev/null @@ -1,410 +0,0 @@ -#ifndef IMPOSTERSTART -#define IMPOSTESTART - -#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Sampling.hlsl" -#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ParallaxMapping.hlsl" - -struct Ray -{ - float3 Origin; - float3 Direction; -}; - -float3 CoordToHemi(float2 coord) -{ - coord = float2(coord.x + coord.y, coord.x - coord.y) * 0.5; - float3 dir = float3(coord.x, 1 - dot(float2(1, 1), abs(coord.xy)), coord.y); - return dir; -} - -float3 CoordToOcta(float2 coord) -{ - float3 dir = float3(coord.x, 1 - dot(1, abs(coord)), coord.y); - if (dir.y < 0) - { - float2 flip = dir.xz >= 0 ? float2(1, 1) : float2(-1, -1); - dir.xz = (1 - abs(dir.zx)) * flip; - } - return dir; -} - -float3 GridToVector(float2 coord, bool IsHemi) -{ - float3 dir; - if (IsHemi) - { - dir = CoordToHemi(coord); - } - else - { - dir = CoordToOcta(coord); - } - return dir; -} - -//for hemisphere -float2 VectorToHemi(float3 dir) -{ - dir.xz /= dot(1.0, abs(dir)); - return float2(dir.x + dir.z, dir.x - dir.z); -} - -float2 VectorToOcta(float3 dir) -{ - dir.xz /= dot(1, abs(dir)); - if (dir.y <= 0) - { - dir.xz = (1 - abs(dir.zx)) * (dir.xz >= 0 ? 1.0 : -1.0); - } - return dir.xz; -} - -//weights base on the triangle -float4 CalculateWeights(float2 uv) -{ - uv = frac(uv); - - float2 oneMinusUV = 1 - uv.xy; - - float4 res; - //frame 0 - res.x = min(oneMinusUV.x, oneMinusUV.y); - //frame 1 - res.y = abs(dot(uv, float2(1.0, -1.0))); - //frame 2 - res.z = min(uv.x, uv.y); - //mask - res.w = saturate(ceil(uv.x - uv.y)); - - return res; -} - -float3 FrameTransformLocal(float3 BillboardPosToCam, float3 normal, out float3 worldX, out float3 worldZ) -{ - float3 upVector = float3 (0, 1, 0); - worldX = normalize(cross(upVector, normal)); - worldZ = normalize(cross(worldX, normal)); - - BillboardPosToCam *= -1.0; - - float3x3 worldToLocal = float3x3(worldX, worldZ, normal); - float3 localRay = normalize(mul(worldToLocal, BillboardPosToCam)); - return localRay; -} - -float2 PlaneIntersectionUV(float3 planeNormal, float3 planeX, float3 planeZ, float3 center, float2 UVscale, Ray ray) -{ - float normalDotOrigin = dot(planeNormal, -ray.Origin);//(p0 - l0) . n - float normalDotRay = dot(planeNormal, ray.Direction);//l.n - float planeDistance = normalDotOrigin / normalDotRay;//distance >0 then intersecting - - //intersect = rayDir * distance + rayPos - float3 intersection = ((ray.Direction * planeDistance) + ray.Origin) - center; - - float dx = dot(planeX, intersection); - float dz = dot(planeZ, intersection); - - float2 uv = float2(0, 0); - - if (planeDistance > 0) - { - uv = -float2(dx, dz); - } - else - { - uv = float2(0, 0); - } - - uv /= UVscale; - uv += float2(0.5, 0.5); - return uv; -} - -float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) -{ - float3 up = normalize(objectSpaceCameraDir); - float3 x = normalize(cross(up, float3(0.0, 1.0, 0.0))); - float3 z = normalize(cross(x, up)); - - uv = uv * 2.0 - 1.0; - - float3 newX = x * uv.x; - float3 newZ = z * uv.y; - - float3 result = newX + newZ; - - return result; -} - -//Calculate Vertex postion and UVs -void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, - out float3 outPos, out float4 outUVGrid, out float4 outUV0, out float4 outUV1, out float4 outUV2) -{ - float framesMinusOne = imposterFrames - 1; - - //camera pos in object space - float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz; - float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); - - //get uv in a single frame - float2 UVscaled = inUV.xy * (1.0 / imposterFrames); - float2 size = imposterSize.xx * 2.0; - - float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); - - //camera to projection vector - float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; - - //BillboardPos position to camera ray - float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); - - Ray ray; - ray.Origin = objectSpaceCameraPos; - ray.Direction = rayDirLocal; - - //set up virtual grid - float2 grid; - if (isHemi) { - objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); - grid = VectorToHemi(objectSpaceCameraDir); - } - else { - grid = VectorToOcta(objectSpaceCameraDir); - } - - grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 - grid *= framesMinusOne;//multiply framesMinusOne to cover the texture - - float2 gridFrac = frac(grid); - float2 gridFloor = floor(grid); - - float4 weights = CalculateWeights(gridFrac); - - //set up for octahedron: - //1.find the nearest 3 frames - //2.base on the grid find the direction intersect with the octahedron - //3.construct the face/plane for that direction - //4.base on the plane and find the virtual uv coord - - //get the 3 nearest frames - float2 frame0 = gridFloor; - float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); - float2 frame2 = gridFloor + float2(1, 1); - - //convert frame coordinate to octahedron direction - float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); - float3 frame1ray = normalize(GridToVector(float2(frame1 / framesMinusOne * 2 - 1), isHemi)); - float3 frame2ray = normalize(GridToVector(float2(frame2 / framesMinusOne * 2 - 1), isHemi)); - - float3 center = float3(0, 0, 0); - - float3 plane0x; - float3 plane0normal = frame0ray; - float3 plane0z; - float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); - - float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); - vUv0 /= imposterFrames; - - float3 plane1x; - float3 plane1normal = frame1ray; - float3 plane1z; - float3 frame1local = FrameTransformLocal(BillboardPosToCam, frame1ray, plane1x, plane1z); - - float2 vUv1 = PlaneIntersectionUV(plane1normal, plane1x, plane1z, center, size, ray); - vUv1 /= imposterFrames; - - float3 plane2x; - float3 plane2normal = frame2ray; - float3 plane2z; - float3 frame2local = FrameTransformLocal(BillboardPosToCam, frame2ray, plane2x, plane2z); - - float2 vUv2 = PlaneIntersectionUV(plane2normal, plane2x, plane2z, center, size, ray); - vUv2 /= imposterFrames; - - frame0local.xy /= imposterFrames; - frame1local.xy /= imposterFrames; - frame2local.xy /= imposterFrames; - - //vert pos - outPos = BillboardPos + imposterOffset; - - //surface - outUVGrid.xy = UVscaled; - outUVGrid.zw = grid; - outUV0 = float4(vUv0.xy, frame0local.xz); - outUV1 = float4(vUv1.xy, frame1local.xz); - outUV2 = float4(vUv2.xy, frame2local.xz);; -} -void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, - out float3 outPos, out float4 outUVGrid, out float4 outUV0) -{ - float framesMinusOne = imposterFrames - 1; - - //camera pos in object space - float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz; - float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); - - //get uv in a single frame - float2 UVscaled = inUV.xy * (1.0 / imposterFrames); - float2 size = imposterSize.xx * 2.0; - - float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); - - //camera to projection vector - float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; - - //BillboardPos position to camera ray - float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); - - Ray ray; - ray.Origin = objectSpaceCameraPos; - ray.Direction = rayDirLocal; - - //set up virtual grid - float2 grid; - if (isHemi) { - objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); - grid = VectorToHemi(objectSpaceCameraDir); - } - else { - grid = VectorToOcta(objectSpaceCameraDir); - } - - grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 - grid *= framesMinusOne;//multiply framesMinusOne to cover the texture - - float2 gridFrac = frac(grid); - float2 gridFloor = floor(grid); - - float4 weights = CalculateWeights(gridFrac); - - //set up for octahedron: - //1.find the nearest 3 frames - //2.base on the grid find the direction intersect with the octahedron - //3.construct the face/plane for that direction - //4.base on the plane and find the virtual uv coord - - //get the 3 nearest frames - float2 frame0 = gridFloor; - float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); - float2 frame2 = gridFloor + float2(1, 1); - - //convert frame coordinate to octahedron direction - float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); - - float3 center = float3(0, 0, 0); - - float3 plane0x; - float3 plane0normal = frame0ray; - float3 plane0z; - float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); - - float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); - vUv0 /= imposterFrames; - - frame0local.xy /= imposterFrames; - - //vert pos - outPos = BillboardPos + imposterOffset; - - //surface - outUVGrid.xy = UVscaled; - outUVGrid.zw = grid; - outUV0 = float4(vUv0.xy, frame0local.xz); - -} -//Sample from UVs -void ImposterSample(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, - in float imposterClip, in float4 inUVGrid, in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) -{ - float2 inUV = inUVGrid.xy; - - float2 fracGrid = frac(inUVGrid.zw); - - float4 weights = CalculateWeights(fracGrid); - - float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; - - float2 frame0 = gridSnap; - float2 frame1 = gridSnap + (lerp(float2(0, 1), float2(1, 0), weights.w) / imposterFrames.xx); - float2 frame2 = gridSnap + (float2(1, 1) / imposterFrames.xx); - - float2 vp0uv = frame0 + inUV0.xy; - float2 vp1uv = frame1 + inUV1.xy; - float2 vp2uv = frame2 + inUV2.xy; - - //frame size ->2048/12 = 170.6 - float frameSize = mapTexelSize.z / imposterFrames; - //actual texture size used -> 170*12 = 2040 - float actualTextureSize = floor(frameSize) * imposterFrames; - //the scalar -> 2048/2040 = 0.99609375 - float scalar = mapTexelSize.z / actualTextureSize; - - vp0uv *= scalar; - vp1uv *= scalar; - vp2uv *= scalar; - - if (parallax != 0) { - - vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - vp1uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); - vp2uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); - } - - // clip out neighboring frames - float2 gridSize = 1.0 / imposterFrames.xx; - float2 bleeds = mapTexelSize.xy * imposterClip; - vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); - vp1uv = clamp(vp1uv, frame1 - bleeds, frame1 + gridSize + bleeds); - vp2uv = clamp(vp2uv, frame2 - bleeds, frame2 + gridSize + bleeds); - - float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)) * weights.x - + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp1uv, ddx(inUV), ddy(inUV)) * weights.y - + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp2uv, ddx(inUV), ddy(inUV)) * weights.z; - - outColor.a = blendedColor.a - imposterClip + 1; - clip(outColor.a); - outColor.rgb = blendedColor.rgb; -} - -void ImposterSample_oneFrame(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, - in float imposterClip, in float4 inUVGrid, in float4 inUV0, in SamplerState ss, out float4 outColor) -{ - float2 inUV = inUVGrid.xy; - - float2 fracGrid = frac(inUVGrid.zw); - - float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; - - float2 frame0 = gridSnap; - - float2 vp0uv = frame0 + inUV0.xy; - - //frame size ->2048/12 = 170.6 - float frameSize = mapTexelSize.z / imposterFrames; - //actual texture size used -> 170*12 = 2040 - float actualTextureSize = floor(frameSize) * imposterFrames; - //the scalar -> 2048/2040 = 0.99609375 - float scalar = mapTexelSize.z / actualTextureSize; - - vp0uv *= scalar; - - if (parallax != 0) { - - vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - } - - // clip out neighboring frames - float2 gridSize = 1.0 / imposterFrames.xx; - float2 bleeds = mapTexelSize.xy * imposterClip; - vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); - - float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)); - - outColor.a = blendedColor.a - imposterClip + 1; - clip(outColor.a); - outColor.rgb = blendedColor.rgb; -} - -#endif diff --git a/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl.meta b/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl.meta deleted file mode 100644 index 30f6948528a..00000000000 --- a/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: d79c6812a6dfb2d4c92954b2620142fe -ShaderIncludeImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: From 44fe29cbdc28412f2c739a07af4f34ae665701cf Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 20 Apr 2023 00:53:07 -0700 Subject: [PATCH 04/20] fixed docs base on Ben's feedback --- com.unity.sg2/Documentation~/Imposter-Sample-Node.md | 6 ++++-- com.unity.sg2/Documentation~/Imposter-UV-Node.md | 6 +++--- com.unity.sg2/Documentation~/previews/ImposterSample.md | 6 ++++-- com.unity.sg2/Documentation~/previews/ImposterUV.md | 4 ++-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md index caec0ba3b9e..a0f639c9cbe 100644 --- a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md @@ -2,7 +2,9 @@ ## Description -The Imposter Sample Node utilizes the three virtual UVs to sample the imposter texture and blends them based on the camera intersection point on the octahedron sphere, thereby achieving accurate sampling results. +Uses the UV coordinates generated by the Imposter UV node to sample an specific imposter texture. +This creates the illusion of a 3D object on a billboard object because the imposter texture's frame changes based on the camera direction and angle. +If the imposter object has more than one texture to sample (e.g. color, normal, mask, occlusion, etc,), multiple Imposter Sample nodes can be used. ## Ports | Name | Direction | Type | Description | @@ -13,7 +15,7 @@ The Imposter Sample Node utilizes the three virtual UVs to sample the imposter t | UV1 | Input | Vector4 | The virtual UV for the second frame | | UV2 | Input | Vector4 | The virtual UV for the third frame | | Grid | Input | Vector4 | The current UV grid, which is used to find the corresponding sample frames | -| Frames | Input | Float | The amount of the imposter frames | +| Frames | Input | Float | The number of the imposter frames in each axis| | Clip | Input | Float | The amount of clipping for a single frame | | Parallax | Input | Float | Parallax strength| | Height Map Channel | Input | Int | The channle of the height map to sample for parallax mapping, if any| diff --git a/com.unity.sg2/Documentation~/Imposter-UV-Node.md b/com.unity.sg2/Documentation~/Imposter-UV-Node.md index 2475bd6df72..49b5a165b3c 100644 --- a/com.unity.sg2/Documentation~/Imposter-UV-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-UV-Node.md @@ -2,17 +2,17 @@ ## Description -The Imposter UV Node calculates the billboard positon and the virtual UVs for sampling. +The Imposter UV Node calculates the billboard position and the UV coordinates needed by the Imposter Sample node. ## Ports | Name | Direction | Type | Description | |:------------ |:-------------|:-----|:---| | In Position | Input | Vector3 | The postion in Object space | | UV | Input | Vector4 | The UV coordinates of the mesh | -| Frames | Input | Float | The amount of the imposter frames | +| Frames | Input | Float | The number of the imposter frames in each axis| | Offset | Input | Float | The offset value from the pivot | | Size | Input | Float | The size of the imposter | -| HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type | +| HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type.ase on hemisphere type. Useful if the object is only seen from above | | Out Positon | Output | Vector3 | The output billboard position | | UV0 | Output | Vector4 | The virtual UV for the base frame | | UV1 | Output | Vector4 | The virtual UV for the second frame | diff --git a/com.unity.sg2/Documentation~/previews/ImposterSample.md b/com.unity.sg2/Documentation~/previews/ImposterSample.md index 214c37725c1..20815029bd9 100644 --- a/com.unity.sg2/Documentation~/previews/ImposterSample.md +++ b/com.unity.sg2/Documentation~/previews/ImposterSample.md @@ -1,5 +1,7 @@ ## Description -Samples from the three virtual UVs and blends them base on the camera intersection point to get the correct result. +Uses the UV coordinates generated by the Imposter UV node to sample an specific imposter texture. +This creates the illusion of a 3D object on a billboard object because the imposter texture's frame changes based on the camera direction and angle. + ## Inputs **Texture** - The texture asset to sample. **Sampler** - The texture sampler to use for sampling the texture. @@ -7,7 +9,7 @@ Samples from the three virtual UVs and blends them base on the camera intersecti **UV1** - The virtual UV for the second frame. **UV2** - The virtual UV for the third frame. **Grid** - The current UV grid, which is used to find the corresponding sample frames. -**Frames** - The amount of the imposter frames +**Frames** - The number of the imposter frames in each axis. **Clip** - The amount of clipping for a single frame. **Parallax** - Parallax strength. **Height Map Channel** - The channle of the height map to sample for parallax mapping, if any. diff --git a/com.unity.sg2/Documentation~/previews/ImposterUV.md b/com.unity.sg2/Documentation~/previews/ImposterUV.md index 43d892ea3df..3c988842ba3 100644 --- a/com.unity.sg2/Documentation~/previews/ImposterUV.md +++ b/com.unity.sg2/Documentation~/previews/ImposterUV.md @@ -4,10 +4,10 @@ Calculates the billboard positon and the virtual UVs for sampling. ## Inputs **InPosition** - The postion in Object space. **UV** - The UV coordinates of the mesh. -**Frames** - The amount of the imposter frames +**Frames** - The number of the imposter frames in each axis. **Offset** - The offset value from the pivot. **Size** - The size of the imposter. -**HemiSphere** - If it's true, calculates the imposter grid and UVs base on hemisphere type. +**HemiSphere** - If it's true, calculates the imposter grid and UVs base on hemisphere type. Useful if the object is only seen from above. ## Output **OutPosition** - The output billboard position. From 0c778621776a7d2be2cbaafa1d538ce246d52b8b Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 20 Apr 2023 00:54:53 -0700 Subject: [PATCH 05/20] more fixes --- .../Input/MeshDeformation/Imposter.hlsl | 11 +++++------ .../Input/MeshDeformation/ImposterUVNode.cs | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl index 66e3fd20cf2..b9dea197096 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl @@ -1,5 +1,5 @@ -#ifndef IMPOSTERSTART -#define IMPOSTESTART +#ifndef SHADERGRAPHIMPOSTER +#define SHADERGRAPHIMPOSTER #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Sampling.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ParallaxMapping.hlsl" @@ -42,7 +42,6 @@ float3 GridToVector(float2 coord, bool IsHemi) return dir; } -//for hemisphere float2 VectorToHemi(float3 dir) { dir.xz /= dot(1.0, abs(dir)); @@ -115,7 +114,7 @@ float2 PlaneIntersectionUV(float3 planeNormal, float3 planeX, float3 planeZ, flo uv = float2(0, 0); } - uv /= UVscale; + // uv /= UVscale; uv += float2(0.5, 0.5); return uv; } @@ -148,9 +147,10 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo //get uv in a single frame float2 UVscaled = inUV.xy * (1.0 / imposterFrames); - float2 size = imposterSize.xx * 2.0; + float2 size = imposterSize.xx * 1.33; float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + BillboardPos *= 0.67; //camera to projection vector float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; @@ -228,7 +228,6 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo //vert pos outPos = BillboardPos + imposterOffset; - //surface outUVGrid.xy = UVscaled; outUVGrid.zw = grid; diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs index 781fbbc94f3..e30b487375e 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs @@ -75,10 +75,12 @@ internal class ImposterUVNode : IStandardNode new ParameterUIDescriptor( name: "Pos", displayName:"In Position", + options: REF.OptionList.Positions, tooltip: "The postiont in Object space" ), new ParameterUIDescriptor( name: "UV", + options: REF.OptionList.UVs, tooltip: "The UV coordinates of the mesh" ), new ParameterUIDescriptor( From 0c7dac1011662ba31abb37e6e6d0dc0e51f12bba Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 20 Apr 2023 01:17:31 -0700 Subject: [PATCH 06/20] get rid of imposter clip input --- .../Input/MeshDeformation/Imposter.hlsl | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl index b9dea197096..d961e0ae67b 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl @@ -114,16 +114,15 @@ float2 PlaneIntersectionUV(float3 planeNormal, float3 planeX, float3 planeZ, flo uv = float2(0, 0); } - // uv /= UVscale; + uv /= UVscale; uv += float2(0.5, 0.5); return uv; } float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) { - float3 up = normalize(objectSpaceCameraDir); - float3 x = normalize(cross(up, float3(0.0, 1.0, 0.0))); - float3 z = normalize(cross(x, up)); + float3 x = normalize(cross(objectSpaceCameraDir, float3(0.0, 1.0, 0.0))); + float3 z = normalize(cross(x, objectSpaceCameraDir)); uv = uv * 2.0 - 1.0; @@ -131,7 +130,6 @@ float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) float3 newZ = z * uv.y; float3 result = newX + newZ; - return result; } @@ -142,7 +140,7 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo float framesMinusOne = imposterFrames - 1; //camera pos in object space - float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz; + float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz - imposterOffset; float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); //get uv in a single frame @@ -228,6 +226,7 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo //vert pos outPos = BillboardPos + imposterOffset; + //surface outUVGrid.xy = UVscaled; outUVGrid.zw = grid; @@ -241,7 +240,7 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame float framesMinusOne = imposterFrames - 1; //camera pos in object space - float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz; + float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz - imposterOffset; float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); //get uv in a single frame @@ -315,7 +314,7 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame } //Sample from UVs void ImposterSample(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, - in float imposterClip, in float4 inUVGrid, in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) + in float4 inUVGrid, in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) { float2 inUV = inUVGrid.xy; @@ -346,29 +345,29 @@ void ImposterSample(in int heightMapChannel, in float3 viewDirTS, in float paral if (parallax != 0) { - vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - vp1uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); - vp2uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); + vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); + vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); } // clip out neighboring frames - float2 gridSize = 1.0 / imposterFrames.xx; - float2 bleeds = mapTexelSize.xy * imposterClip; - vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); - vp1uv = clamp(vp1uv, frame1 - bleeds, frame1 + gridSize + bleeds); - vp2uv = clamp(vp2uv, frame2 - bleeds, frame2 + gridSize + bleeds); + //float2 gridSize = 1.0 / imposterFrames.xx; + //float2 bleeds = mapTexelSize.xy * imposterClip; + //vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); + //vp1uv = clamp(vp1uv, frame1 - bleeds, frame1 + gridSize + bleeds); + //vp2uv = clamp(vp2uv, frame2 - bleeds, frame2 + gridSize + bleeds); float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)) * weights.x + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp1uv, ddx(inUV), ddy(inUV)) * weights.y + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp2uv, ddx(inUV), ddy(inUV)) * weights.z; - outColor.a = blendedColor.a - imposterClip + 1; - clip(outColor.a); + outColor.a = blendedColor.a; + //clip(outColor.a); outColor.rgb = blendedColor.rgb; } void ImposterSample_oneFrame(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, - in float imposterClip, in float4 inUVGrid, in float4 inUV0, in SamplerState ss, out float4 outColor) + in float4 inUVGrid, in float4 inUV0, in SamplerState ss, out float4 outColor) { float2 inUV = inUVGrid.xy; @@ -394,14 +393,10 @@ void ImposterSample_oneFrame(in int heightMapChannel, in float3 viewDirTS, in fl vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); } - // clip out neighboring frames - float2 gridSize = 1.0 / imposterFrames.xx; - float2 bleeds = mapTexelSize.xy * imposterClip; - vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)); - outColor.a = blendedColor.a - imposterClip + 1; + outColor.a = blendedColor.a; clip(outColor.a); outColor.rgb = blendedColor.rgb; } From bbe953f3e44aaeee56d4f0ccc246c1f704e5a8a8 Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 20 Apr 2023 01:19:57 -0700 Subject: [PATCH 07/20] get rid of clip imput on node --- com.unity.sg2/Documentation~/Imposter-Sample-Node.md | 5 ++--- .../Documentation~/previews/ImposterSample.md | 1 - .../Input/MeshDeformation/ImposterSampleNode.cs | 10 ++-------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md index a0f639c9cbe..5caddd175ac 100644 --- a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md @@ -16,7 +16,6 @@ If the imposter object has more than one texture to sample (e.g. color, normal, | UV2 | Input | Vector4 | The virtual UV for the third frame | | Grid | Input | Vector4 | The current UV grid, which is used to find the corresponding sample frames | | Frames | Input | Float | The number of the imposter frames in each axis| -| Clip | Input | Float | The amount of clipping for a single frame | | Parallax | Input | Float | Parallax strength| | Height Map Channel | Input | Int | The channle of the height map to sample for parallax mapping, if any| | RGBA | Output | Vector3 | A vector4 from the sampled texture | @@ -57,11 +56,11 @@ The Imposter Sample Node [!include[nodes-controls](./snippets/nodes-controls.md) ### ThreeFrames ``` -ImposterSample(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); +ImposterSample(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); ``` ### OneFrame ``` -ImposterSample_oneFrame(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, Sampler.samplerstate, RGBA); +ImposterSample_oneFrame(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Grid, UV0, Sampler.samplerstate, RGBA); ``` diff --git a/com.unity.sg2/Documentation~/previews/ImposterSample.md b/com.unity.sg2/Documentation~/previews/ImposterSample.md index 20815029bd9..0e53340bc93 100644 --- a/com.unity.sg2/Documentation~/previews/ImposterSample.md +++ b/com.unity.sg2/Documentation~/previews/ImposterSample.md @@ -10,7 +10,6 @@ This creates the illusion of a 3D object on a billboard object because the impos **UV2** - The virtual UV for the third frame. **Grid** - The current UV grid, which is used to find the corresponding sample frames. **Frames** - The number of the imposter frames in each axis. -**Clip** - The amount of clipping for a single frame. **Parallax** - Parallax strength. **Height Map Channel** - The channle of the height map to sample for parallax mapping, if any. diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs index 7f7459798cf..6aa415138cc 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs @@ -14,7 +14,7 @@ internal class ImposterSampleNode : IStandardNode functions: new FunctionDescriptor[] { new( "ThreeFrames", - @"ImposterSample(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", + @"ImposterSample(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), @@ -24,7 +24,6 @@ internal class ImposterSampleNode : IStandardNode new ParameterDescriptor("UV2", TYPE.Vec4, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), - new ParameterDescriptor("Clip", TYPE.Float, Usage.In, new float[] {1f}), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), @@ -37,7 +36,7 @@ internal class ImposterSampleNode : IStandardNode ), new( "OneFrame", - @"ImposterSample_oneFrame(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, Sampler.samplerstate, RGBA);", + @"ImposterSample_oneFrame(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Grid, UV0, Sampler.samplerstate, RGBA);", new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), @@ -45,7 +44,6 @@ internal class ImposterSampleNode : IStandardNode new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), - new ParameterDescriptor("Clip", TYPE.Float, Usage.In, new float[] {1f}), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), @@ -103,10 +101,6 @@ internal class ImposterSampleNode : IStandardNode name: "Frames", tooltip: "The amount of the imposter frames" ), - new ParameterUIDescriptor( - name: "Clip", - tooltip: "The amount of clipping for a single frame" - ), new ParameterUIDescriptor( name: "Parallax", tooltip: "Adds parallax effect the port value is true" From 7aadd3d801c98e5be0033134205092f9bc5457b4 Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 20 Apr 2023 02:34:54 -0700 Subject: [PATCH 08/20] move most of math to imposter uv node --- .../ShaderGraphLibrary/Imposter.hlsl | 408 ++++++++++++++++++ 1 file changed, 408 insertions(+) create mode 100644 com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl diff --git a/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl b/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl new file mode 100644 index 00000000000..4ed411fd06b --- /dev/null +++ b/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl @@ -0,0 +1,408 @@ +#ifndef SHADERGRAPHIMPOSTER +#define SHADERGRAPHIMPOSTER + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Sampling.hlsl" +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ParallaxMapping.hlsl" + +struct Ray +{ + float3 Origin; + float3 Direction; +}; + +float3 CoordToHemi(float2 coord) +{ + coord = float2(coord.x + coord.y, coord.x - coord.y) * 0.5; + float3 dir = float3(coord.x, 1 - dot(float2(1, 1), abs(coord.xy)), coord.y); + return dir; +} + +float3 CoordToOcta(float2 coord) +{ + float3 dir = float3(coord.x, 1 - dot(1, abs(coord)), coord.y); + if (dir.y < 0) + { + float2 flip = dir.xz >= 0 ? float2(1, 1) : float2(-1, -1); + dir.xz = (1 - abs(dir.zx)) * flip; + } + return dir; +} + +float3 GridToVector(float2 coord, bool IsHemi) +{ + float3 dir; + if (IsHemi) + { + dir = CoordToHemi(coord); + } + else + { + dir = CoordToOcta(coord); + } + return dir; +} + +//for hemisphere +float2 VectorToHemi(float3 dir) +{ + dir.xz /= dot(1.0, abs(dir)); + return float2(dir.x + dir.z, dir.x - dir.z); +} + +float2 VectorToOcta(float3 dir) +{ + dir.xz /= dot(1, abs(dir)); + if (dir.y <= 0) + { + dir.xz = (1 - abs(dir.zx)) * (dir.xz >= 0 ? 1.0 : -1.0); + } + return dir.xz; +} + +//weights base on the triangle +float4 CalculateWeights(float2 uv) +{ + uv = frac(uv); + + float2 oneMinusUV = 1 - uv.xy; + + float4 res; + //frame 0 + res.x = min(oneMinusUV.x, oneMinusUV.y); + //frame 1 + res.y = abs(dot(uv, float2(1.0, -1.0))); + //frame 2 + res.z = min(uv.x, uv.y); + //mask + res.w = saturate(ceil(uv.x - uv.y)); + + return res; +} + +float3 FrameTransformLocal(float3 BillboardPosToCam, float3 normal, out float3 worldX, out float3 worldZ) +{ + float3 upVector = float3 (0, 1, 0); + worldX = normalize(cross(upVector, normal)); + worldZ = normalize(cross(worldX, normal)); + + BillboardPosToCam *= -1.0; + + float3x3 worldToLocal = float3x3(worldX, worldZ, normal); + float3 localRay = normalize(mul(worldToLocal, BillboardPosToCam)); + return localRay; +} + +float2 PlaneIntersectionUV(float3 planeNormal, float3 planeX, float3 planeZ, float3 center, float2 UVscale, Ray ray) +{ + float normalDotOrigin = dot(planeNormal, -ray.Origin);//(p0 - l0) . n + float normalDotRay = dot(planeNormal, ray.Direction);//l.n + float planeDistance = normalDotOrigin / normalDotRay;//distance >0 then intersecting + + //intersect = rayDir * distance + rayPos + float3 intersection = ((ray.Direction * planeDistance) + ray.Origin) - center; + + float dx = dot(planeX, intersection); + float dz = dot(planeZ, intersection); + + float2 uv = float2(0, 0); + + if (planeDistance > 0) + { + uv = -float2(dx, dz); + } + else + { + uv = float2(0, 0); + } + + uv /= UVscale; + uv += float2(0.5, 0.5); + return uv; +} + +float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) +{ + float3 x = normalize(cross(objectSpaceCameraDir, float3(0.0, 1.0, 0.0))); + float3 z = normalize(cross(x, objectSpaceCameraDir)); + + uv = uv * 2.0 - 1.0; + + float3 newX = x * uv.x; + float3 newZ = z * uv.y; + + float3 result = newX + newZ; + return result; +} + +//Calculate Vertex postion and UVs +void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, + in bool isHemi, in float parallax, in float3 viewDirTS, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, + out float3 outPos, out float4 outWeights, out float4 outUV0, out float4 outUV1, out float4 outUV2, out float4 outUVGrid) +{ + float framesMinusOne = imposterFrames - 1; + + //camera pos in object space + float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz - imposterOffset; + float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); + + //get uv in a single frame + float2 UVscaled = inUV.xy * (1.0 / imposterFrames); + float2 size = imposterSize.xx*1.33; + + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + BillboardPos *= 0.67; + + //camera to projection vector + float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; + + //BillboardPos position to camera ray + float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); + + Ray ray; + ray.Origin = objectSpaceCameraPos; + ray.Direction = rayDirLocal; + + //set up virtual grid + float2 grid; + if (isHemi) { + objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); + grid = VectorToHemi(objectSpaceCameraDir); + } + else { + grid = VectorToOcta(objectSpaceCameraDir); + } + + grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 + grid *= framesMinusOne;//multiply framesMinusOne to cover the texture + + float2 gridFrac = frac(grid); + float2 gridFloor = floor(grid); + + float4 weights = CalculateWeights(gridFrac); + + //set up for octahedron: + //1.find the nearest 3 frames + //2.base on the grid find the direction intersect with the octahedron + //3.construct the face/plane for that direction + //4.base on the plane and find the virtual uv coord + + //get the 3 nearest frames + float2 frame0 = gridFloor; + float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); + float2 frame2 = gridFloor + float2(1, 1); + + //convert frame coordinate to octahedron direction + float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); + float3 frame1ray = normalize(GridToVector(float2(frame1 / framesMinusOne * 2 - 1), isHemi)); + float3 frame2ray = normalize(GridToVector(float2(frame2 / framesMinusOne * 2 - 1), isHemi)); + + float3 center = float3(0, 0, 0); + + float3 plane0x; + float3 plane0normal = frame0ray; + float3 plane0z; + float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); + + float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); + vUv0 /= imposterFrames; + + float3 plane1x; + float3 plane1normal = frame1ray; + float3 plane1z; + float3 frame1local = FrameTransformLocal(BillboardPosToCam, frame1ray, plane1x, plane1z); + + float2 vUv1 = PlaneIntersectionUV(plane1normal, plane1x, plane1z, center, size, ray); + vUv1 /= imposterFrames; + + float3 plane2x; + float3 plane2normal = frame2ray; + float3 plane2z; + float3 frame2local = FrameTransformLocal(BillboardPosToCam, frame2ray, plane2x, plane2z); + + float2 vUv2 = PlaneIntersectionUV(plane2normal, plane2x, plane2z, center, size, ray); + vUv2 /= imposterFrames; + + frame0local.xy /= imposterFrames; + frame1local.xy /= imposterFrames; + frame2local.xy /= imposterFrames; + + //vert pos + outPos = BillboardPos + imposterOffset; + + float2 gridSnap = floor(grid) / imposterFrames.xx; + + float2 frame0grid = gridSnap; + float2 frame1grid = gridSnap + (lerp(float2(0, 1), float2(1, 0), weights.w) / imposterFrames.xx); + float2 frame2grid = gridSnap + (float2(1, 1) / imposterFrames.xx); + + float2 vp0uv = frame0grid + vUv0.xy; + float2 vp1uv = frame1grid + vUv1.xy; + float2 vp2uv = frame2grid + vUv2.xy; + + if (parallax != 0) { + + //vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + //vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); + //vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); + } + + //surface + outUV0 = float4(vp0uv, vp0uv); + outUV1 = float4(vp1uv, vp1uv); + outUV2 = float4(vp2uv, vp2uv); + outWeights = weights; + outUVGrid.xy = UVscaled; + outUVGrid.zw = grid; +} +void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, + out float3 outPos, out float4 outUVGrid, out float4 outUV0) +{ + float framesMinusOne = imposterFrames - 1; + + //camera pos in object space + float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz - imposterOffset; + float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); + + //get uv in a single frame + float2 UVscaled = inUV.xy * (1.0 / imposterFrames); + float2 size = imposterSize.xx * 2.0; + + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + + //camera to projection vector + float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; + + //BillboardPos position to camera ray + float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); + + Ray ray; + ray.Origin = objectSpaceCameraPos; + ray.Direction = rayDirLocal; + + //set up virtual grid + float2 grid; + if (isHemi) { + objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); + grid = VectorToHemi(objectSpaceCameraDir); + } + else { + grid = VectorToOcta(objectSpaceCameraDir); + } + + grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 + grid *= framesMinusOne;//multiply framesMinusOne to cover the texture + + float2 gridFrac = frac(grid); + float2 gridFloor = floor(grid); + + float4 weights = CalculateWeights(gridFrac); + + //set up for octahedron: + //1.find the nearest 3 frames + //2.base on the grid find the direction intersect with the octahedron + //3.construct the face/plane for that direction + //4.base on the plane and find the virtual uv coord + + //get the 3 nearest frames + float2 frame0 = gridFloor; + float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); + float2 frame2 = gridFloor + float2(1, 1); + + //convert frame coordinate to octahedron direction + float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); + + float3 center = float3(0, 0, 0); + + float3 plane0x; + float3 plane0normal = frame0ray; + float3 plane0z; + float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); + + float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); + vUv0 /= imposterFrames; + + frame0local.xy /= imposterFrames; + + //vert pos + outPos = BillboardPos + imposterOffset; + + //surface + outUVGrid.xy = UVscaled; + outUVGrid.zw = grid; + outUV0 = float4(vUv0.xy, frame0local.xz); + +} +//Sample from UVs +void ImposterSample( in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, in float4 weights, in float4 inUVGrid, + in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) +{ + //frame size ->2048/12 = 170.6 + float frameSize = mapTexelSize.z / imposterFrames; + //actual texture size used -> 170*12 = 2040 + float actualTextureSize = floor(frameSize) * imposterFrames; + //the scalar -> 2048/2040 = 0.99609375 + float scalar = mapTexelSize.z / actualTextureSize; + + inUV0 *= scalar; + inUV1 *= scalar; + inUV2 *= scalar; + + //if (parallax != 0) { + + // vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + // vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); + // vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); + //} + + // clip out neighboring frames + //float2 gridSize = 1.0 / imposterFrames.xx; + //float2 bleeds = mapTexelSize.xy * imposterClip; + //vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); + //vp1uv = clamp(vp1uv, frame1 - bleeds, frame1 + gridSize + bleeds); + //vp2uv = clamp(vp2uv, frame2 - bleeds, frame2 + gridSize + bleeds); + + float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV0, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.x + + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV1, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.y + + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV2, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.z; + + outColor.a = blendedColor.a; + //clip(outColor.a); + outColor.rgb = blendedColor.rgb; +} + +void ImposterSample_oneFrame(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, + in float4 inUVGrid, in float4 inUV0, in SamplerState ss, out float4 outColor) +{ + float2 inUV = inUVGrid.xy; + + float2 fracGrid = frac(inUVGrid.zw); + + float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; + + float2 frame0 = gridSnap; + + float2 vp0uv = frame0 + inUV0.xy; + + //frame size ->2048/12 = 170.6 + float frameSize = mapTexelSize.z / imposterFrames; + //actual texture size used -> 170*12 = 2040 + float actualTextureSize = floor(frameSize) * imposterFrames; + //the scalar -> 2048/2040 = 0.99609375 + float scalar = mapTexelSize.z / actualTextureSize; + + vp0uv *= scalar; + + if (parallax != 0) { + + vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + } + + + float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)); + + outColor.a = blendedColor.a; + clip(outColor.a); + outColor.rgb = blendedColor.rgb; +} + +#endif From ad08bc32187a4038013a8791e6345d3a1147041c Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 20 Apr 2023 02:39:40 -0700 Subject: [PATCH 09/20] Revert "move most of math to imposter uv node" This reverts commit 7aadd3d801c98e5be0033134205092f9bc5457b4. --- .../ShaderGraphLibrary/Imposter.hlsl | 408 ------------------ 1 file changed, 408 deletions(-) delete mode 100644 com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl diff --git a/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl b/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl deleted file mode 100644 index 4ed411fd06b..00000000000 --- a/com.unity.shadergraph/ShaderGraphLibrary/Imposter.hlsl +++ /dev/null @@ -1,408 +0,0 @@ -#ifndef SHADERGRAPHIMPOSTER -#define SHADERGRAPHIMPOSTER - -#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Sampling.hlsl" -#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ParallaxMapping.hlsl" - -struct Ray -{ - float3 Origin; - float3 Direction; -}; - -float3 CoordToHemi(float2 coord) -{ - coord = float2(coord.x + coord.y, coord.x - coord.y) * 0.5; - float3 dir = float3(coord.x, 1 - dot(float2(1, 1), abs(coord.xy)), coord.y); - return dir; -} - -float3 CoordToOcta(float2 coord) -{ - float3 dir = float3(coord.x, 1 - dot(1, abs(coord)), coord.y); - if (dir.y < 0) - { - float2 flip = dir.xz >= 0 ? float2(1, 1) : float2(-1, -1); - dir.xz = (1 - abs(dir.zx)) * flip; - } - return dir; -} - -float3 GridToVector(float2 coord, bool IsHemi) -{ - float3 dir; - if (IsHemi) - { - dir = CoordToHemi(coord); - } - else - { - dir = CoordToOcta(coord); - } - return dir; -} - -//for hemisphere -float2 VectorToHemi(float3 dir) -{ - dir.xz /= dot(1.0, abs(dir)); - return float2(dir.x + dir.z, dir.x - dir.z); -} - -float2 VectorToOcta(float3 dir) -{ - dir.xz /= dot(1, abs(dir)); - if (dir.y <= 0) - { - dir.xz = (1 - abs(dir.zx)) * (dir.xz >= 0 ? 1.0 : -1.0); - } - return dir.xz; -} - -//weights base on the triangle -float4 CalculateWeights(float2 uv) -{ - uv = frac(uv); - - float2 oneMinusUV = 1 - uv.xy; - - float4 res; - //frame 0 - res.x = min(oneMinusUV.x, oneMinusUV.y); - //frame 1 - res.y = abs(dot(uv, float2(1.0, -1.0))); - //frame 2 - res.z = min(uv.x, uv.y); - //mask - res.w = saturate(ceil(uv.x - uv.y)); - - return res; -} - -float3 FrameTransformLocal(float3 BillboardPosToCam, float3 normal, out float3 worldX, out float3 worldZ) -{ - float3 upVector = float3 (0, 1, 0); - worldX = normalize(cross(upVector, normal)); - worldZ = normalize(cross(worldX, normal)); - - BillboardPosToCam *= -1.0; - - float3x3 worldToLocal = float3x3(worldX, worldZ, normal); - float3 localRay = normalize(mul(worldToLocal, BillboardPosToCam)); - return localRay; -} - -float2 PlaneIntersectionUV(float3 planeNormal, float3 planeX, float3 planeZ, float3 center, float2 UVscale, Ray ray) -{ - float normalDotOrigin = dot(planeNormal, -ray.Origin);//(p0 - l0) . n - float normalDotRay = dot(planeNormal, ray.Direction);//l.n - float planeDistance = normalDotOrigin / normalDotRay;//distance >0 then intersecting - - //intersect = rayDir * distance + rayPos - float3 intersection = ((ray.Direction * planeDistance) + ray.Origin) - center; - - float dx = dot(planeX, intersection); - float dz = dot(planeZ, intersection); - - float2 uv = float2(0, 0); - - if (planeDistance > 0) - { - uv = -float2(dx, dz); - } - else - { - uv = float2(0, 0); - } - - uv /= UVscale; - uv += float2(0.5, 0.5); - return uv; -} - -float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) -{ - float3 x = normalize(cross(objectSpaceCameraDir, float3(0.0, 1.0, 0.0))); - float3 z = normalize(cross(x, objectSpaceCameraDir)); - - uv = uv * 2.0 - 1.0; - - float3 newX = x * uv.x; - float3 newZ = z * uv.y; - - float3 result = newX + newZ; - return result; -} - -//Calculate Vertex postion and UVs -void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, - in bool isHemi, in float parallax, in float3 viewDirTS, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, - out float3 outPos, out float4 outWeights, out float4 outUV0, out float4 outUV1, out float4 outUV2, out float4 outUVGrid) -{ - float framesMinusOne = imposterFrames - 1; - - //camera pos in object space - float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz - imposterOffset; - float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); - - //get uv in a single frame - float2 UVscaled = inUV.xy * (1.0 / imposterFrames); - float2 size = imposterSize.xx*1.33; - - float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); - BillboardPos *= 0.67; - - //camera to projection vector - float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; - - //BillboardPos position to camera ray - float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); - - Ray ray; - ray.Origin = objectSpaceCameraPos; - ray.Direction = rayDirLocal; - - //set up virtual grid - float2 grid; - if (isHemi) { - objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); - grid = VectorToHemi(objectSpaceCameraDir); - } - else { - grid = VectorToOcta(objectSpaceCameraDir); - } - - grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 - grid *= framesMinusOne;//multiply framesMinusOne to cover the texture - - float2 gridFrac = frac(grid); - float2 gridFloor = floor(grid); - - float4 weights = CalculateWeights(gridFrac); - - //set up for octahedron: - //1.find the nearest 3 frames - //2.base on the grid find the direction intersect with the octahedron - //3.construct the face/plane for that direction - //4.base on the plane and find the virtual uv coord - - //get the 3 nearest frames - float2 frame0 = gridFloor; - float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); - float2 frame2 = gridFloor + float2(1, 1); - - //convert frame coordinate to octahedron direction - float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); - float3 frame1ray = normalize(GridToVector(float2(frame1 / framesMinusOne * 2 - 1), isHemi)); - float3 frame2ray = normalize(GridToVector(float2(frame2 / framesMinusOne * 2 - 1), isHemi)); - - float3 center = float3(0, 0, 0); - - float3 plane0x; - float3 plane0normal = frame0ray; - float3 plane0z; - float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); - - float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); - vUv0 /= imposterFrames; - - float3 plane1x; - float3 plane1normal = frame1ray; - float3 plane1z; - float3 frame1local = FrameTransformLocal(BillboardPosToCam, frame1ray, plane1x, plane1z); - - float2 vUv1 = PlaneIntersectionUV(plane1normal, plane1x, plane1z, center, size, ray); - vUv1 /= imposterFrames; - - float3 plane2x; - float3 plane2normal = frame2ray; - float3 plane2z; - float3 frame2local = FrameTransformLocal(BillboardPosToCam, frame2ray, plane2x, plane2z); - - float2 vUv2 = PlaneIntersectionUV(plane2normal, plane2x, plane2z, center, size, ray); - vUv2 /= imposterFrames; - - frame0local.xy /= imposterFrames; - frame1local.xy /= imposterFrames; - frame2local.xy /= imposterFrames; - - //vert pos - outPos = BillboardPos + imposterOffset; - - float2 gridSnap = floor(grid) / imposterFrames.xx; - - float2 frame0grid = gridSnap; - float2 frame1grid = gridSnap + (lerp(float2(0, 1), float2(1, 0), weights.w) / imposterFrames.xx); - float2 frame2grid = gridSnap + (float2(1, 1) / imposterFrames.xx); - - float2 vp0uv = frame0grid + vUv0.xy; - float2 vp1uv = frame1grid + vUv1.xy; - float2 vp2uv = frame2grid + vUv2.xy; - - if (parallax != 0) { - - //vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - //vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); - //vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); - } - - //surface - outUV0 = float4(vp0uv, vp0uv); - outUV1 = float4(vp1uv, vp1uv); - outUV2 = float4(vp2uv, vp2uv); - outWeights = weights; - outUVGrid.xy = UVscaled; - outUVGrid.zw = grid; -} -void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, - out float3 outPos, out float4 outUVGrid, out float4 outUV0) -{ - float framesMinusOne = imposterFrames - 1; - - //camera pos in object space - float3 objectSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz - imposterOffset; - float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); - - //get uv in a single frame - float2 UVscaled = inUV.xy * (1.0 / imposterFrames); - float2 size = imposterSize.xx * 2.0; - - float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); - - //camera to projection vector - float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; - - //BillboardPos position to camera ray - float3 BillboardPosToCam = normalize(objectSpaceCameraPos - BillboardPos); - - Ray ray; - ray.Origin = objectSpaceCameraPos; - ray.Direction = rayDirLocal; - - //set up virtual grid - float2 grid; - if (isHemi) { - objectSpaceCameraDir.y = max(0.001, objectSpaceCameraDir.y); - grid = VectorToHemi(objectSpaceCameraDir); - } - else { - grid = VectorToOcta(objectSpaceCameraDir); - } - - grid = saturate(grid * 0.5 + 0.5); //scale to 0 to 1 - grid *= framesMinusOne;//multiply framesMinusOne to cover the texture - - float2 gridFrac = frac(grid); - float2 gridFloor = floor(grid); - - float4 weights = CalculateWeights(gridFrac); - - //set up for octahedron: - //1.find the nearest 3 frames - //2.base on the grid find the direction intersect with the octahedron - //3.construct the face/plane for that direction - //4.base on the plane and find the virtual uv coord - - //get the 3 nearest frames - float2 frame0 = gridFloor; - float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); - float2 frame2 = gridFloor + float2(1, 1); - - //convert frame coordinate to octahedron direction - float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); - - float3 center = float3(0, 0, 0); - - float3 plane0x; - float3 plane0normal = frame0ray; - float3 plane0z; - float3 frame0local = FrameTransformLocal(BillboardPosToCam, frame0ray, plane0x, plane0z); - - float2 vUv0 = PlaneIntersectionUV(plane0normal, plane0x, plane0z, center, size, ray); - vUv0 /= imposterFrames; - - frame0local.xy /= imposterFrames; - - //vert pos - outPos = BillboardPos + imposterOffset; - - //surface - outUVGrid.xy = UVscaled; - outUVGrid.zw = grid; - outUV0 = float4(vUv0.xy, frame0local.xz); - -} -//Sample from UVs -void ImposterSample( in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, in float4 weights, in float4 inUVGrid, - in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) -{ - //frame size ->2048/12 = 170.6 - float frameSize = mapTexelSize.z / imposterFrames; - //actual texture size used -> 170*12 = 2040 - float actualTextureSize = floor(frameSize) * imposterFrames; - //the scalar -> 2048/2040 = 0.99609375 - float scalar = mapTexelSize.z / actualTextureSize; - - inUV0 *= scalar; - inUV1 *= scalar; - inUV2 *= scalar; - - //if (parallax != 0) { - - // vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - // vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); - // vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); - //} - - // clip out neighboring frames - //float2 gridSize = 1.0 / imposterFrames.xx; - //float2 bleeds = mapTexelSize.xy * imposterClip; - //vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); - //vp1uv = clamp(vp1uv, frame1 - bleeds, frame1 + gridSize + bleeds); - //vp2uv = clamp(vp2uv, frame2 - bleeds, frame2 + gridSize + bleeds); - - float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV0, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.x - + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV1, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.y - + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV2, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.z; - - outColor.a = blendedColor.a; - //clip(outColor.a); - outColor.rgb = blendedColor.rgb; -} - -void ImposterSample_oneFrame(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, - in float4 inUVGrid, in float4 inUV0, in SamplerState ss, out float4 outColor) -{ - float2 inUV = inUVGrid.xy; - - float2 fracGrid = frac(inUVGrid.zw); - - float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; - - float2 frame0 = gridSnap; - - float2 vp0uv = frame0 + inUV0.xy; - - //frame size ->2048/12 = 170.6 - float frameSize = mapTexelSize.z / imposterFrames; - //actual texture size used -> 170*12 = 2040 - float actualTextureSize = floor(frameSize) * imposterFrames; - //the scalar -> 2048/2040 = 0.99609375 - float scalar = mapTexelSize.z / actualTextureSize; - - vp0uv *= scalar; - - if (parallax != 0) { - - vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - } - - - float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)); - - outColor.a = blendedColor.a; - clip(outColor.a); - outColor.rgb = blendedColor.rgb; -} - -#endif From 8b716a3747d5e1cbb2130ae41f35e7aaa5f4babb Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 20 Apr 2023 02:50:47 -0700 Subject: [PATCH 10/20] sg2 changes --- .../Input/MeshDeformation/Imposter.hlsl | 72 ++++++++++--------- .../MeshDeformation/ImposterSampleNode.cs | 23 ++---- .../Input/MeshDeformation/ImposterUVNode.cs | 43 +++++++++-- 3 files changed, 84 insertions(+), 54 deletions(-) diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl index d961e0ae67b..e87d118526d 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl @@ -134,8 +134,9 @@ float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) } //Calculate Vertex postion and UVs -void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, - out float3 outPos, out float4 outUVGrid, out float4 outUV0, out float4 outUV1, out float4 outUV2) +void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, + in bool isHemi, in float parallax, in float3 viewDirTS, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, + out float3 outPos, out float4 outWeights, out float4 outUV0, out float4 outUV1, out float4 outUV2, out float4 outUVGrid) { float framesMinusOne = imposterFrames - 1; @@ -227,12 +228,30 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo //vert pos outPos = BillboardPos + imposterOffset; + float2 gridSnap = floor(grid) / imposterFrames.xx; + + float2 frame0grid = gridSnap; + float2 frame1grid = gridSnap + (lerp(float2(0, 1), float2(1, 0), weights.w) / imposterFrames.xx); + float2 frame2grid = gridSnap + (float2(1, 1) / imposterFrames.xx); + + float2 vp0uv = frame0grid + vUv0.xy; + float2 vp1uv = frame1grid + vUv1.xy; + float2 vp2uv = frame2grid + vUv2.xy; + + if (parallax != 0) { + + //vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + //vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); + //vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); + } + //surface + outUV0 = float4(vp0uv, vp0uv); + outUV1 = float4(vp1uv, vp1uv); + outUV2 = float4(vp2uv, vp2uv); + outWeights = weights; outUVGrid.xy = UVscaled; outUVGrid.zw = grid; - outUV0 = float4(vUv0.xy, frame0local.xz); - outUV1 = float4(vUv1.xy, frame1local.xz); - outUV2 = float4(vUv2.xy, frame2local.xz);; } void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, out float3 outPos, out float4 outUVGrid, out float4 outUV0) @@ -312,26 +331,11 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame outUV0 = float4(vUv0.xy, frame0local.xz); } + //Sample from UVs -void ImposterSample(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, - in float4 inUVGrid, in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) +void ImposterSample(in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, in float4 weights, in float4 inUVGrid, + in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) { - float2 inUV = inUVGrid.xy; - - float2 fracGrid = frac(inUVGrid.zw); - - float4 weights = CalculateWeights(fracGrid); - - float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; - - float2 frame0 = gridSnap; - float2 frame1 = gridSnap + (lerp(float2(0, 1), float2(1, 0), weights.w) / imposterFrames.xx); - float2 frame2 = gridSnap + (float2(1, 1) / imposterFrames.xx); - - float2 vp0uv = frame0 + inUV0.xy; - float2 vp1uv = frame1 + inUV1.xy; - float2 vp2uv = frame2 + inUV2.xy; - //frame size ->2048/12 = 170.6 float frameSize = mapTexelSize.z / imposterFrames; //actual texture size used -> 170*12 = 2040 @@ -339,16 +343,16 @@ void ImposterSample(in int heightMapChannel, in float3 viewDirTS, in float paral //the scalar -> 2048/2040 = 0.99609375 float scalar = mapTexelSize.z / actualTextureSize; - vp0uv *= scalar; - vp1uv *= scalar; - vp2uv *= scalar; + inUV0 *= scalar; + inUV1 *= scalar; + inUV2 *= scalar; - if (parallax != 0) { + //if (parallax != 0) { - vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); - vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); - } + // vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); + // vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); + // vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); + //} // clip out neighboring frames //float2 gridSize = 1.0 / imposterFrames.xx; @@ -357,9 +361,9 @@ void ImposterSample(in int heightMapChannel, in float3 viewDirTS, in float paral //vp1uv = clamp(vp1uv, frame1 - bleeds, frame1 + gridSize + bleeds); //vp2uv = clamp(vp2uv, frame2 - bleeds, frame2 + gridSize + bleeds); - float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)) * weights.x - + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp1uv, ddx(inUV), ddy(inUV)) * weights.y - + SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp2uv, ddx(inUV), ddy(inUV)) * weights.z; + float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV0, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.x + + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV1, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.y + + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV2, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.z; outColor.a = blendedColor.a; //clip(outColor.a); diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs index 6aa415138cc..f9917c20481 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs @@ -14,7 +14,7 @@ internal class ImposterSampleNode : IStandardNode functions: new FunctionDescriptor[] { new( "ThreeFrames", - @"ImposterSample(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", + @"ImposterSample Frames, Texture.tex, Texture.texelSize, Weights, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), @@ -23,10 +23,8 @@ internal class ImposterSampleNode : IStandardNode new ParameterDescriptor("UV1", TYPE.Vec4, Usage.In), new ParameterDescriptor("UV2", TYPE.Vec4, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), + new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), - new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), - new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), - new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out) }, new string[] @@ -35,18 +33,16 @@ internal class ImposterSampleNode : IStandardNode } ), new( - "OneFrame", - @"ImposterSample_oneFrame(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Grid, UV0, Sampler.samplerstate, RGBA);", + "OneFrame",//TODO: change back to one frame + @"ImposterSample Frames, Texture.tex, Texture.texelSize, Weights, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), + new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), - new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), - new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), - new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out) }, new string[] @@ -102,13 +98,8 @@ internal class ImposterSampleNode : IStandardNode tooltip: "The amount of the imposter frames" ), new ParameterUIDescriptor( - name: "Parallax", - tooltip: "Adds parallax effect the port value is true" - ), - new ParameterUIDescriptor( - name: "HeightMapChannel", - displayName:"Heigh Map Channel", - tooltip: "The texture channel to sample from for the parallax effect" + name: "Weights", + tooltip: "Blending weights for three frames" ), new ParameterUIDescriptor( name: "RGBA", diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs index e30b487375e..0ddc9f48dac 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs @@ -14,7 +14,8 @@ internal class ImposterUVNode : IStandardNode functions: new FunctionDescriptor[] { new( "ThreeFrames", -" ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, OutPos, Grid, UV0, UV1, UV2);", +" ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, ViewDirectionTS, HeightMapChannel, " + + " Sampler, Texture, OutPos, Weights, UV0, UV1, UV2, Grid);", new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), @@ -23,10 +24,16 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), + new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), + new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), + new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), new ParameterDescriptor("UV0", TYPE.Vec4, Usage.Out), new ParameterDescriptor("UV1", TYPE.Vec4, Usage.Out), new ParameterDescriptor("UV2", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("Weights", TYPE.Vec4, Usage.Out), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) }, new string[] @@ -34,18 +41,25 @@ internal class ImposterUVNode : IStandardNode "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" } ),new( - "OneFrame", -" ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, HemiSphere, OutPos, Grid, UV0);", + "OneFrame",//TODO: change it back to one frame +" ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, ViewDirectionTS, HeightMapChannel, " + + " Sampler, Texture, OutPos, Weights, UV0, UV1, UV2, Grid);", new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), - new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1f}), + new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), + new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), + new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), + new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), new ParameterDescriptor("UV0", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("Weights", TYPE.Vec4, Usage.Out), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) }, new string[] @@ -99,6 +113,23 @@ internal class ImposterUVNode : IStandardNode name: "HemiSphere", tooltip: "If it's true, calculate imposter grid and UVs base on hemisphere type." ), + new ParameterUIDescriptor( + name: "Texture", + tooltip: "The texture asset to sample" + ), + new ParameterUIDescriptor( + name: "Sampler", + tooltip: "The texture sampler to use for sampling the texture" + ), + new ParameterUIDescriptor( + name: "Parallax", + tooltip: "Adds parallax effect the port value is true" + ), + new ParameterUIDescriptor( + name: "HeightMapChannel", + displayName:"Heigh Map Channel", + tooltip: "The texture channel to sample from for the parallax effect" + ), new ParameterUIDescriptor( name: "OutPos", displayName:"Out Position", @@ -115,6 +146,10 @@ internal class ImposterUVNode : IStandardNode new ParameterUIDescriptor( name: "UV2", tooltip: "The virtual UV for the third frame" + ), + new ParameterUIDescriptor( + name: "Weights", + tooltip: "Blending weights for three frames" ), new ParameterUIDescriptor( name: "Grid", From d3bb9936db7c8675380bb7618a4dfa5d1275e6dc Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Fri, 21 Apr 2023 14:29:11 -0700 Subject: [PATCH 11/20] sg2 imposter nodes: move/reorder ports --- .../Input/MeshDeformation/Imposter.hlsl | 145 ++++++++---------- .../MeshDeformation/ImposterSampleNode.cs | 11 +- .../Input/MeshDeformation/ImposterUVNode.cs | 20 ++- 3 files changed, 83 insertions(+), 93 deletions(-) diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl index e87d118526d..c92f7521359 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl @@ -42,6 +42,7 @@ float3 GridToVector(float2 coord, bool IsHemi) return dir; } +//for hemisphere float2 VectorToHemi(float3 dir) { dir.xz /= dot(1.0, abs(dir)); @@ -58,24 +59,23 @@ float2 VectorToOcta(float3 dir) return dir.xz; } -//weights base on the triangle float4 CalculateWeights(float2 uv) { uv = frac(uv); float2 oneMinusUV = 1 - uv.xy; - float4 res; + float4 weights; //frame 0 - res.x = min(oneMinusUV.x, oneMinusUV.y); + weights.x = min(oneMinusUV.x, oneMinusUV.y); //frame 1 - res.y = abs(dot(uv, float2(1.0, -1.0))); + weights.y = abs(dot(uv, float2(1.0, -1.0))); //frame 2 - res.z = min(uv.x, uv.y); + weights.z = min(uv.x, uv.y); //mask - res.w = saturate(ceil(uv.x - uv.y)); + weights.w = saturate(ceil(uv.x - uv.y)); - return res; + return weights; } float3 FrameTransformLocal(float3 BillboardPosToCam, float3 normal, out float3 worldX, out float3 worldZ) @@ -119,6 +119,8 @@ float2 PlaneIntersectionUV(float3 planeNormal, float3 planeX, float3 planeZ, flo return uv; } + + float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) { float3 x = normalize(cross(objectSpaceCameraDir, float3(0.0, 1.0, 0.0))); @@ -135,8 +137,8 @@ float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) //Calculate Vertex postion and UVs void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, - in bool isHemi, in float parallax, in float3 viewDirTS, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, - out float3 outPos, out float4 outWeights, out float4 outUV0, out float4 outUV1, out float4 outUV2, out float4 outUVGrid) + in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, + out float3 outPos, out float4 outWeights, out float2 outUV0, out float2 outUV1, out float2 outUV2, out float4 outUVGrid) { float framesMinusOne = imposterFrames - 1; @@ -190,7 +192,7 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); float2 frame2 = gridFloor + float2(1, 1); - //convert frame coordinate to octahedron direction + //convert frame coord to octahedron ray float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); float3 frame1ray = normalize(GridToVector(float2(frame1 / framesMinusOne * 2 - 1), isHemi)); float3 frame2ray = normalize(GridToVector(float2(frame2 / framesMinusOne * 2 - 1), isHemi)); @@ -225,9 +227,6 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo frame1local.xy /= imposterFrames; frame2local.xy /= imposterFrames; - //vert pos - outPos = BillboardPos + imposterOffset; - float2 gridSnap = floor(grid) / imposterFrames.xx; float2 frame0grid = gridSnap; @@ -240,21 +239,29 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo if (parallax != 0) { - //vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - //vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); - //vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(heightMap, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); + float h0 = SAMPLE_TEXTURE2D(heightMap, ss, vp0uv)[heightMapChannel]; + float h1 = SAMPLE_TEXTURE2D(heightMap, ss, vp0uv)[heightMapChannel]; + float h2 = SAMPLE_TEXTURE2D(heightMap, ss, vp0uv)[heightMapChannel]; + + vp0uv += (0.5 - h0) * frame0local.xy * parallax; + vp1uv += (0.5 - h1) * frame1local.xy * parallax; + vp2uv += (0.5 - h2) * frame2local.xy * parallax; } + //vert pos + outPos = BillboardPos + imposterOffset; + //surface - outUV0 = float4(vp0uv, vp0uv); - outUV1 = float4(vp1uv, vp1uv); - outUV2 = float4(vp2uv, vp2uv); + outUV0 = vp0uv; + outUV1 = vp1uv; + outUV2 = vp2uv; outWeights = weights; outUVGrid.xy = UVscaled; outUVGrid.zw = grid; } -void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in bool isHemi, - out float3 outPos, out float4 outUVGrid, out float4 outUV0) +void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, + in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, + out float3 outPos, out float2 outUV0, out float4 outUVGrid) { float framesMinusOne = imposterFrames - 1; @@ -264,9 +271,10 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame //get uv in a single frame float2 UVscaled = inUV.xy * (1.0 / imposterFrames); - float2 size = imposterSize.xx * 2.0; + float2 size = imposterSize.xx * 1.33; float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + BillboardPos *= 0.67; //camera to projection vector float3 rayDirLocal = BillboardPos - objectSpaceCameraPos; @@ -294,21 +302,8 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame float2 gridFrac = frac(grid); float2 gridFloor = floor(grid); - float4 weights = CalculateWeights(gridFrac); - - //set up for octahedron: - //1.find the nearest 3 frames - //2.base on the grid find the direction intersect with the octahedron - //3.construct the face/plane for that direction - //4.base on the plane and find the virtual uv coord - - //get the 3 nearest frames - float2 frame0 = gridFloor; - float2 frame1 = gridFloor + lerp(float2(0, 1), float2(1, 0), weights.w); - float2 frame2 = gridFloor + float2(1, 1); - - //convert frame coordinate to octahedron direction - float3 frame0ray = normalize(GridToVector(float2(frame0 / framesMinusOne * 2 - 1), isHemi)); + //convert frame coord to octahedron ray + float3 frame0ray = normalize(GridToVector(float2(gridFloor / framesMinusOne * 2 - 1), isHemi)); float3 center = float3(0, 0, 0); @@ -322,19 +317,27 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame frame0local.xy /= imposterFrames; + float2 gridSnap = floor(grid) / imposterFrames.xx; + float2 frame0grid = gridSnap; + float2 vp0uv = frame0grid + vUv0.xy; + + if (parallax != 0) { + float h0 = SAMPLE_TEXTURE2D(heightMap, ss, vp0uv)[heightMapChannel]; + vp0uv += (0.5 - h0) * frame0local.xy * parallax; + } + //vert pos outPos = BillboardPos + imposterOffset; //surface + outUV0 = vp0uv; outUVGrid.xy = UVscaled; outUVGrid.zw = grid; - outUV0 = float4(vUv0.xy, frame0local.xz); } - //Sample from UVs -void ImposterSample(in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, in float4 weights, in float4 inUVGrid, - in float4 inUV0, in float4 inUV1, in float4 inUV2, in SamplerState ss, out float4 outColor) +void ImposterSample(in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, in float4 weights, in float imposterFrameClip, in float4 inUVGrid, + in float2 inUV0, in float2 inUV1, in float2 inUV2, in SamplerState ss, out float4 outColor) { //frame size ->2048/12 = 170.6 float frameSize = mapTexelSize.z / imposterFrames; @@ -347,42 +350,26 @@ void ImposterSample(in float imposterFrames, in texture2D Texture, in float4 map inUV1 *= scalar; inUV2 *= scalar; - //if (parallax != 0) { - - // vp0uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - // vp1uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp1uv, heightMapChannel); - // vp2uv = ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp2uv, heightMapChannel); - //} + float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; + float2 frame0grid = gridSnap; + float2 frame1grid = gridSnap + (lerp(float2(0, 1), float2(1, 0), weights.w) / imposterFrames.xx); + float2 frame2grid = gridSnap + (float2(1, 1) / imposterFrames.xx); - // clip out neighboring frames - //float2 gridSize = 1.0 / imposterFrames.xx; - //float2 bleeds = mapTexelSize.xy * imposterClip; - //vp0uv = clamp(vp0uv, frame0 - bleeds, frame0 + gridSize + bleeds); - //vp1uv = clamp(vp1uv, frame1 - bleeds, frame1 + gridSize + bleeds); - //vp2uv = clamp(vp2uv, frame2 - bleeds, frame2 + gridSize + bleeds); + //clip out neighboring frames + float2 gridSize = 1.0 / imposterFrames.xx; + float2 bleeds = mapTexelSize.xy * imposterFrameClip; + inUV0 = clamp(inUV0, frame0grid - bleeds, frame0grid + gridSize + bleeds); + inUV1 = clamp(inUV1, frame1grid - bleeds, frame1grid + gridSize + bleeds); + inUV2 = clamp(inUV2, frame2grid - bleeds, frame2grid + gridSize + bleeds); - float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV0, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.x + outColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV0, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.x + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV1, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.y + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV2, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.z; - - outColor.a = blendedColor.a; - //clip(outColor.a); - outColor.rgb = blendedColor.rgb; } -void ImposterSample_oneFrame(in int heightMapChannel, in float3 viewDirTS, in float parallax, in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, - in float4 inUVGrid, in float4 inUV0, in SamplerState ss, out float4 outColor) +void ImposterSample_oneFrame(in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, in float imposterFrameClip, in float4 inUVGrid, + in float2 inUV0, in SamplerState ss, out float4 outColor) { - float2 inUV = inUVGrid.xy; - - float2 fracGrid = frac(inUVGrid.zw); - - float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; - - float2 frame0 = gridSnap; - - float2 vp0uv = frame0 + inUV0.xy; - //frame size ->2048/12 = 170.6 float frameSize = mapTexelSize.z / imposterFrames; //actual texture size used -> 170*12 = 2040 @@ -390,19 +377,17 @@ void ImposterSample_oneFrame(in int heightMapChannel, in float3 viewDirTS, in fl //the scalar -> 2048/2040 = 0.99609375 float scalar = mapTexelSize.z / actualTextureSize; - vp0uv *= scalar; - - if (parallax != 0) { - - vp0uv += ParallaxMappingChannel(TEXTURE2D_ARGS(Texture, ss), viewDirTS, parallax * 0.01, vp0uv, heightMapChannel); - } + inUV0 *= scalar; + float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; + float2 frame0grid = gridSnap; - float4 blendedColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, vp0uv, ddx(inUV), ddy(inUV)); + //clip out neighboring frames + float2 gridSize = 1.0 / imposterFrames.xx; + float2 bleeds = mapTexelSize.xy * imposterFrameClip; + inUV0 = clamp(inUV0, frame0grid - bleeds, frame0grid + gridSize + bleeds); - outColor.a = blendedColor.a; - clip(outColor.a); - outColor.rgb = blendedColor.rgb; + outColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV0, ddx(inUVGrid.xy), ddy(inUVGrid.xy)); } #endif diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs index f9917c20481..64276104519 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs @@ -14,7 +14,7 @@ internal class ImposterSampleNode : IStandardNode functions: new FunctionDescriptor[] { new( "ThreeFrames", - @"ImposterSample Frames, Texture.tex, Texture.texelSize, Weights, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", + @"ImposterSample( Frames, Texture.tex, Texture.texelSize, Weights, Clip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), @@ -25,6 +25,7 @@ internal class ImposterSampleNode : IStandardNode new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), + new ParameterDescriptor("Clip", TYPE.Float, Usage.Static, new float[] {0.1f}), new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out) }, new string[] @@ -34,7 +35,7 @@ internal class ImposterSampleNode : IStandardNode ), new( "OneFrame",//TODO: change back to one frame - @"ImposterSample Frames, Texture.tex, Texture.texelSize, Weights, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", + @"ImposterSample_oneFrame (Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, Sampler.samplerstate, RGBA);", new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), @@ -43,6 +44,7 @@ internal class ImposterSampleNode : IStandardNode new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), + new ParameterDescriptor("Clip", TYPE.Float, Usage.Static, new float[] {0.1f}), new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out) }, new string[] @@ -101,6 +103,11 @@ internal class ImposterSampleNode : IStandardNode name: "Weights", tooltip: "Blending weights for three frames" ), + new ParameterUIDescriptor( + name: "Clip", + displayName:"Imposter Frame Clip", + tooltip: "The value to clamp between imposter frame. Useful when doing parallax mapping." + ), new ParameterUIDescriptor( name: "RGBA", tooltip: "A vector4 from the sampled texture" diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs index 0ddc9f48dac..f77aacf655b 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs @@ -14,8 +14,8 @@ internal class ImposterUVNode : IStandardNode functions: new FunctionDescriptor[] { new( "ThreeFrames", -" ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, ViewDirectionTS, HeightMapChannel, " + - " Sampler, Texture, OutPos, Weights, UV0, UV1, UV2, Grid);", +" ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, HeightMapChannel, " + + " Sampler.samplerstate, Texture.tex, OutPos, Weights, UV0, UV1, UV2, Grid);", new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), @@ -27,12 +27,11 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), - new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("UV0", TYPE.Vec4, Usage.Out), - new ParameterDescriptor("UV1", TYPE.Vec4, Usage.Out), - new ParameterDescriptor("UV2", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("UV0", TYPE.Vec2, Usage.Out), + new ParameterDescriptor("UV1", TYPE.Vec2, Usage.Out), + new ParameterDescriptor("UV2", TYPE.Vec2, Usage.Out), new ParameterDescriptor("Weights", TYPE.Vec4, Usage.Out), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) }, @@ -41,9 +40,9 @@ internal class ImposterUVNode : IStandardNode "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" } ),new( - "OneFrame",//TODO: change it back to one frame -" ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, ViewDirectionTS, HeightMapChannel, " + - " Sampler, Texture, OutPos, Weights, UV0, UV1, UV2, Grid);", + "OneFrame", +" ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, HeightMapChannel, " + + " Sampler.samplerstate, Texture.tex, OutPos, UV0, Grid);", new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), @@ -55,11 +54,9 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), - new ParameterDescriptor("ViewDirectionTS", TYPE.Vec3, Usage.Local, REF.TangentSpace_ViewDirection), new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), new ParameterDescriptor("UV0", TYPE.Vec4, Usage.Out), - new ParameterDescriptor("Weights", TYPE.Vec4, Usage.Out), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) }, new string[] @@ -115,6 +112,7 @@ internal class ImposterUVNode : IStandardNode ), new ParameterUIDescriptor( name: "Texture", + displayName:"Height Map", tooltip: "The texture asset to sample" ), new ParameterUIDescriptor( From 99f8a3030e7a491ce79d5507364ffa6357fa46b4 Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Fri, 21 Apr 2023 14:30:43 -0700 Subject: [PATCH 12/20] move billboard node to correct location --- .../{Utility => Input/MeshDeformation}/BillboardNode.cs | 0 .../{Utility => Input/MeshDeformation}/BillboardNode.cs.meta | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/{Utility => Input/MeshDeformation}/BillboardNode.cs (100%) rename com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/{Utility => Input/MeshDeformation}/BillboardNode.cs.meta (100%) diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/BillboardNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/BillboardNode.cs similarity index 100% rename from com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/BillboardNode.cs rename to com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/BillboardNode.cs diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/BillboardNode.cs.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/BillboardNode.cs.meta similarity index 100% rename from com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/BillboardNode.cs.meta rename to com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/BillboardNode.cs.meta From b88a51c57feee892f5bb590428efe02d79b35b3e Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Fri, 21 Apr 2023 14:38:29 -0700 Subject: [PATCH 13/20] move imposter nodes to utility folder --- .../{Input/MeshDeformation => Utility}/Imposter.hlsl | 0 .../{Input/MeshDeformation => Utility}/Imposter.hlsl.meta | 0 .../MeshDeformation => Utility}/ImposterSampleNode.cs | 4 ++-- .../MeshDeformation => Utility}/ImposterSampleNode.cs.meta | 0 .../{Input/MeshDeformation => Utility}/ImposterUVNode.cs | 6 +++--- .../MeshDeformation => Utility}/ImposterUVNode.cs.meta | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/{Input/MeshDeformation => Utility}/Imposter.hlsl (100%) rename com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/{Input/MeshDeformation => Utility}/Imposter.hlsl.meta (100%) rename com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/{Input/MeshDeformation => Utility}/ImposterSampleNode.cs (96%) rename com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/{Input/MeshDeformation => Utility}/ImposterSampleNode.cs.meta (100%) rename com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/{Input/MeshDeformation => Utility}/ImposterUVNode.cs (96%) rename com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/{Input/MeshDeformation => Utility}/ImposterUVNode.cs.meta (100%) diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl similarity index 100% rename from com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl rename to com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl.meta similarity index 100% rename from com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl.meta rename to com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl.meta diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs similarity index 96% rename from com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs rename to com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs index 64276104519..469d479f292 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs @@ -30,7 +30,7 @@ internal class ImposterSampleNode : IStandardNode }, new string[] { - "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl\"" } ), new( @@ -49,7 +49,7 @@ internal class ImposterSampleNode : IStandardNode }, new string[] { - "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl\"" } ) } diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs.meta similarity index 100% rename from com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterSampleNode.cs.meta rename to com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs.meta diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs similarity index 96% rename from com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs rename to com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs index f77aacf655b..a62f6c4f4ef 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs @@ -37,7 +37,7 @@ internal class ImposterUVNode : IStandardNode }, new string[] { - "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl\"" } ),new( "OneFrame", @@ -56,12 +56,12 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("UV0", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("UV0", TYPE.Vec2, Usage.Out), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) }, new string[] { - "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/Imposter.hlsl\"" + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl\"" } ) } diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs.meta similarity index 100% rename from com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Input/MeshDeformation/ImposterUVNode.cs.meta rename to com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs.meta From 32098b4878db826a3e107021505c4984da2fdc86 Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Fri, 21 Apr 2023 16:27:13 -0700 Subject: [PATCH 14/20] more fixes --- .../Documentation~/Imposter-Sample-Node.md | 21 ++++++----- .../Documentation~/Imposter-UV-Node.md | 22 +++++++----- .../Documentation~/previews/ImposterSample.md | 11 ++++-- .../Documentation~/previews/ImposterUV.md | 4 +++ .../Utility/ImposterSampleNode.cs | 35 +++++++++++++++---- .../Utility/ImposterUVNode.cs | 23 ++++++------ 6 files changed, 79 insertions(+), 37 deletions(-) diff --git a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md index 5caddd175ac..9ba04c8feda 100644 --- a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md @@ -11,14 +11,19 @@ If the imposter object has more than one texture to sample (e.g. color, normal, |:------------ |:-------------|:-----|:---| | Texture | Input | Texture2D | The texture asset to sample | | Sampler | Input | Sampler State | The texture sampler to use for sampling the texture | -| UV0 | Input | Vector4 | The virtual UV for the base frame | -| UV1 | Input | Vector4 | The virtual UV for the second frame | -| UV2 | Input | Vector4 | The virtual UV for the third frame | +| UV0 | Input | Vector2 | The virtual UV for the base frame | +| UV1 | Input | Vector2 | The virtual UV for the second frame | +| UV2 | Input | Vector2 | The virtual UV for the third frame | | Grid | Input | Vector4 | The current UV grid, which is used to find the corresponding sample frames | | Frames | Input | Float | The number of the imposter frames in each axis| -| Parallax | Input | Float | Parallax strength| -| Height Map Channel | Input | Int | The channle of the height map to sample for parallax mapping, if any| +| Weights | Input | Float | The blending values in between the slected three frames| +| Imposter Frame Clip | Input | Float | The clamping value in between frames| | RGBA | Output | Vector3 | A vector4 from the sampled texture | +| RGB | Output | Vector3 | A vector3 from the sampled texture | +| R | Output | Vector3 | The r channel of the sampled texture | +| G | Output | Vector3 | The g channel of the sampled texture | +| B | Output | Vector3 | The b channel of the sampled texture | +| A | Output | Vector3 | The a channel of the sampled texture | ## Controls @@ -44,7 +49,7 @@ The Imposter Sample Node [!include[nodes-controls](./snippets/nodes-controls.md) One Frame -Calculates only one frame for better performance. +Calculates only one frame for better performance. UV1, UV2 and Weights inputs won't be shown. @@ -56,11 +61,11 @@ The Imposter Sample Node [!include[nodes-controls](./snippets/nodes-controls.md) ### ThreeFrames ``` -ImposterSample(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); +ImposterSample(ImposterFrames, Texture.tex, Texture.texelSize, Weights,IpmosterClip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); ``` ### OneFrame ``` -ImposterSample_oneFrame(HeightMapChannel, ViewDirectionTS, Parallax, Frames, Texture.tex, Texture.texelSize, Grid, UV0, Sampler.samplerstate, RGBA); +ImposterSample_oneFrame(ImposterFrames, Texture.tex, Texture.texelSize, Weights,IpmosterClip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); ``` diff --git a/com.unity.sg2/Documentation~/Imposter-UV-Node.md b/com.unity.sg2/Documentation~/Imposter-UV-Node.md index 49b5a165b3c..f18bc1121f3 100644 --- a/com.unity.sg2/Documentation~/Imposter-UV-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-UV-Node.md @@ -8,16 +8,21 @@ The Imposter UV Node calculates the billboard position and the UV coordinates ne | Name | Direction | Type | Description | |:------------ |:-------------|:-----|:---| | In Position | Input | Vector3 | The postion in Object space | -| UV | Input | Vector4 | The UV coordinates of the mesh | +| In UV | Input | Vector4 | The UV coordinates of the mesh | | Frames | Input | Float | The number of the imposter frames in each axis| | Offset | Input | Float | The offset value from the pivot | | Size | Input | Float | The size of the imposter | -| HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type.ase on hemisphere type. Useful if the object is only seen from above | +| Height map | Input | Texture2D | The height map texture to sample | +| Sampler | Input | Sampler State | The texture sampler to use for sampling the texture | +| Parallax | Input | Float | Parallax strength| +| Height Map Channel | Input | Int | The channle of the height map to sample for parallax mapping, if any| +| HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type.This is Useful if the imposter object will only be seen from above | | Out Positon | Output | Vector3 | The output billboard position | -| UV0 | Output | Vector4 | The virtual UV for the base frame | -| UV1 | Output | Vector4 | The virtual UV for the second frame | -| UV2 | Output | Vector4 | The virtual UV for the third frame | +| UV0 | Output | Vector2 | The virtual UV for the base frame | +| UV1 | Output | Vector2 | The virtual UV for the second frame | +| UV2 | Output | Vector2 | The virtual UV for the third frame | | Grid | Output | Vector4 | The current UV grid, which is used to find the corresponding sample frames | +| Weights | Output | Vector4 | he blending values in between the slected three frames | ## Controls @@ -44,7 +49,7 @@ The Imposter UV Node [!include[nodes-controls](./snippets/nodes-controls.md)] One Frame -Calculates only one frame for better performance. +Calculates only one frame for better performance. UV1, UV2 and Weights outputs won't be shown. @@ -56,10 +61,11 @@ The Imposter UV Node [!include[nodes-controls](./snippets/nodes-controls.md)] ### ThreeFrames ``` -ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, OutPos, Grid, UV0, UV1, UV2)``` +ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, OutPos, Weights, Grid, UV0, UV1, UV2) +``` ### OneFrame ``` -ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, HemiSphere, OutPos, Grid, UV0); +ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, OutPos, Grid, UV0); ``` diff --git a/com.unity.sg2/Documentation~/previews/ImposterSample.md b/com.unity.sg2/Documentation~/previews/ImposterSample.md index 0e53340bc93..d953f681061 100644 --- a/com.unity.sg2/Documentation~/previews/ImposterSample.md +++ b/com.unity.sg2/Documentation~/previews/ImposterSample.md @@ -9,12 +9,17 @@ This creates the illusion of a 3D object on a billboard object because the impos **UV1** - The virtual UV for the second frame. **UV2** - The virtual UV for the third frame. **Grid** - The current UV grid, which is used to find the corresponding sample frames. +**Weights** - The blending values in between the slected three frames. **Frames** - The number of the imposter frames in each axis. -**Parallax** - Parallax strength. -**Height Map Channel** - The channle of the height map to sample for parallax mapping, if any. +**Imposter Frame Clip** - The clamping value in between frames. ## Output **RGBA** - A vector4 from the sampled texture. +**RGB** - A vector3 from the sampled texture. +**R** - The r channel of the sampled texture. +**G** - The g channel of the sampled texture. +**B** - The b channel of the sampled texture. +**A** - The a channel of the sampled texture. ## Controls -**Sample Type** - Select whether to sample three frames or one frame, three frames for smoother result, one frame for better performance. +**Sample Type** - Select whether to sample three frames or one frame, three frames for smoother result, one frame for better performance. diff --git a/com.unity.sg2/Documentation~/previews/ImposterUV.md b/com.unity.sg2/Documentation~/previews/ImposterUV.md index 3c988842ba3..ea310de3709 100644 --- a/com.unity.sg2/Documentation~/previews/ImposterUV.md +++ b/com.unity.sg2/Documentation~/previews/ImposterUV.md @@ -7,6 +7,10 @@ Calculates the billboard positon and the virtual UVs for sampling. **Frames** - The number of the imposter frames in each axis. **Offset** - The offset value from the pivot. **Size** - The size of the imposter. +**Height Map** - The height map texture to sample. +**Sampler** - The texture sampler to use for sampling the texture. +**Parallax** - Parallax strength. +**Height Map Channel** - The channle of the height map to sample for parallax mapping, if any. **HemiSphere** - If it's true, calculates the imposter grid and UVs base on hemisphere type. Useful if the object is only seen from above. ## Output diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs index 469d479f292..9c6b09fd924 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs @@ -14,19 +14,30 @@ internal class ImposterSampleNode : IStandardNode functions: new FunctionDescriptor[] { new( "ThreeFrames", - @"ImposterSample( Frames, Texture.tex, Texture.texelSize, Weights, Clip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA);", + @"ImposterSample( Frames, Texture.tex, Texture.texelSize, Weights, Clip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); + RGB = RGBA.rgb; + R = RGBA.r; + G = RGBA.g; + B = RGBA.b; + A = RGBA.a; +", new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), - new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), new ParameterDescriptor("UV1", TYPE.Vec4, Usage.In), new ParameterDescriptor("UV2", TYPE.Vec4, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), new ParameterDescriptor("Clip", TYPE.Float, Usage.Static, new float[] {0.1f}), - new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out) + new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("RGB", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("R", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("G", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("B", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("A", TYPE.Vec3, Usage.Out) }, new string[] { @@ -35,18 +46,28 @@ internal class ImposterSampleNode : IStandardNode ), new( "OneFrame",//TODO: change back to one frame - @"ImposterSample_oneFrame (Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, Sampler.samplerstate, RGBA);", + @"ImposterSample_oneFrame (Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, Sampler.samplerstate, RGBA); + RGB = RGBA.rgb; + R = RGBA.r; + G = RGBA.g; + B = RGBA.b; + A = RGBA.a; +", new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), - new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), new ParameterDescriptor("Clip", TYPE.Float, Usage.Static, new float[] {0.1f}), - new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out) - }, + new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("RGB", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("R", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("G", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("B", TYPE.Vec3, Usage.Out), + new ParameterDescriptor("A", TYPE.Vec3, Usage.Out) }, new string[] { "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl\"" diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs index a62f6c4f4ef..5f8398c6575 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs @@ -19,21 +19,21 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), + new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), + new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), - new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), - new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), - new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), - new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), new ParameterDescriptor("UV0", TYPE.Vec2, Usage.Out), new ParameterDescriptor("UV1", TYPE.Vec2, Usage.Out), new ParameterDescriptor("UV2", TYPE.Vec2, Usage.Out), - new ParameterDescriptor("Weights", TYPE.Vec4, Usage.Out), - new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) + new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("Weights", TYPE.Vec4, Usage.Out) }, new string[] { @@ -46,15 +46,15 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), + new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), + new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), - new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), - new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), - new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), - new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), new ParameterDescriptor("UV0", TYPE.Vec2, Usage.Out), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) @@ -90,7 +90,8 @@ internal class ImposterUVNode : IStandardNode tooltip: "The postiont in Object space" ), new ParameterUIDescriptor( - name: "UV", + name: "inUV", + displayName:"In UV", options: REF.OptionList.UVs, tooltip: "The UV coordinates of the mesh" ), From b23a3e8e78da4ecc6bac9f3b5912f94c8a1a0e05 Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Sun, 23 Apr 2023 18:49:14 -0700 Subject: [PATCH 15/20] change input ports order --- .../StandardDefinitions/Utility/ImposterSampleNode.cs | 4 ++-- .../StandardDefinitions/Utility/ImposterUVNode.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs index 9c6b09fd924..257a09bfa0c 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs @@ -24,10 +24,10 @@ internal class ImposterSampleNode : IStandardNode new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), new ParameterDescriptor("UV1", TYPE.Vec4, Usage.In), new ParameterDescriptor("UV2", TYPE.Vec4, Usage.In), - new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), @@ -56,8 +56,8 @@ internal class ImposterSampleNode : IStandardNode new ParameterDescriptor[] { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), - new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs index 5f8398c6575..6c43f4a279e 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs @@ -21,12 +21,12 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), - new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), - new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), + new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), new ParameterDescriptor("UV0", TYPE.Vec2, Usage.Out), @@ -48,12 +48,12 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), - new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), - new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), + new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), new ParameterDescriptor("UV0", TYPE.Vec2, Usage.Out), From 94653a0b1fb4e67a59df1d4fb8ddfb45dd036771 Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Wed, 26 Apr 2023 13:22:57 -0700 Subject: [PATCH 16/20] move frames to uv node and add a texel size input on uv node --- .../Documentation~/Imposter-Sample-Node.md | 14 ++- .../Documentation~/Imposter-UV-Node.md | 12 ++- .../Documentation~/previews/ImposterSample.md | 2 - .../Documentation~/previews/ImposterUV.md | 6 +- .../StandardDefinitions/Utility/Imposter.hlsl | 98 +++++++++---------- .../Utility/ImposterSampleNode.cs | 44 +++------ .../Utility/ImposterUVNode.cs | 40 +++++--- 7 files changed, 104 insertions(+), 112 deletions(-) diff --git a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md index 9ba04c8feda..1303df58cd4 100644 --- a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md @@ -15,15 +15,13 @@ If the imposter object has more than one texture to sample (e.g. color, normal, | UV1 | Input | Vector2 | The virtual UV for the second frame | | UV2 | Input | Vector2 | The virtual UV for the third frame | | Grid | Input | Vector4 | The current UV grid, which is used to find the corresponding sample frames | -| Frames | Input | Float | The number of the imposter frames in each axis| | Weights | Input | Float | The blending values in between the slected three frames| -| Imposter Frame Clip | Input | Float | The clamping value in between frames| | RGBA | Output | Vector3 | A vector4 from the sampled texture | | RGB | Output | Vector3 | A vector3 from the sampled texture | -| R | Output | Vector3 | The r channel of the sampled texture | -| G | Output | Vector3 | The g channel of the sampled texture | -| B | Output | Vector3 | The b channel of the sampled texture | -| A | Output | Vector3 | The a channel of the sampled texture | +| R | Output | Float | The r channel of the sampled texture | +| G | Output | Float | The g channel of the sampled texture | +| B | Output | Float | The b channel of the sampled texture | +| A | Output | Float | The a channel of the sampled texture | ## Controls @@ -61,11 +59,11 @@ The Imposter Sample Node [!include[nodes-controls](./snippets/nodes-controls.md) ### ThreeFrames ``` -ImposterSample(ImposterFrames, Texture.tex, Texture.texelSize, Weights,IpmosterClip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); +ImposterSample( Texture.tex, TexelSize, Weights, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); ``` ### OneFrame ``` -ImposterSample_oneFrame(ImposterFrames, Texture.tex, Texture.texelSize, Weights,IpmosterClip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); +ImposterSample_oneFrame( Texture.tex, TexelSize, Weights, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); ``` diff --git a/com.unity.sg2/Documentation~/Imposter-UV-Node.md b/com.unity.sg2/Documentation~/Imposter-UV-Node.md index f18bc1121f3..5beee1f05b4 100644 --- a/com.unity.sg2/Documentation~/Imposter-UV-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-UV-Node.md @@ -10,13 +10,15 @@ The Imposter UV Node calculates the billboard position and the UV coordinates ne | In Position | Input | Vector3 | The postion in Object space | | In UV | Input | Vector4 | The UV coordinates of the mesh | | Frames | Input | Float | The number of the imposter frames in each axis| -| Offset | Input | Float | The offset value from the pivot | | Size | Input | Float | The size of the imposter | +| Offset | Input | Float | The offset value from the pivot | +| Frame Clipping Threshold | Input | Float | The clamping value for the neighboring frames most useful when parallax mapping is enabled | +| Texel Size | Input | Vector4 | The texel size of the heightmap or the textures will be sampled in the Imposter Sample Node. | +| HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type.This is Useful if the imposter object will only be seen from above | +| Parallax | Input | Float | Parallax strength, if it equals to 0 than he parallax related control won't affect the outputs.| | Height map | Input | Texture2D | The height map texture to sample | | Sampler | Input | Sampler State | The texture sampler to use for sampling the texture | -| Parallax | Input | Float | Parallax strength| | Height Map Channel | Input | Int | The channle of the height map to sample for parallax mapping, if any| -| HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type.This is Useful if the imposter object will only be seen from above | | Out Positon | Output | Vector3 | The output billboard position | | UV0 | Output | Vector2 | The virtual UV for the base frame | | UV1 | Output | Vector2 | The virtual UV for the second frame | @@ -61,11 +63,11 @@ The Imposter UV Node [!include[nodes-controls](./snippets/nodes-controls.md)] ### ThreeFrames ``` -ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, OutPos, Weights, Grid, UV0, UV1, UV2) +ImposterUV(Pos, inUV, Frames, Offset, Size, imposterFrameClip, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, TexelSize, OutPos, Weights, Grid, UV0, UV1, UV2) ``` ### OneFrame ``` -ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, OutPos, Grid, UV0); +ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, imposterFrameClip, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, TexelSize, OutPos, Grid, UV0); ``` diff --git a/com.unity.sg2/Documentation~/previews/ImposterSample.md b/com.unity.sg2/Documentation~/previews/ImposterSample.md index d953f681061..244f4de87f2 100644 --- a/com.unity.sg2/Documentation~/previews/ImposterSample.md +++ b/com.unity.sg2/Documentation~/previews/ImposterSample.md @@ -10,8 +10,6 @@ This creates the illusion of a 3D object on a billboard object because the impos **UV2** - The virtual UV for the third frame. **Grid** - The current UV grid, which is used to find the corresponding sample frames. **Weights** - The blending values in between the slected three frames. -**Frames** - The number of the imposter frames in each axis. -**Imposter Frame Clip** - The clamping value in between frames. ## Output **RGBA** - A vector4 from the sampled texture. diff --git a/com.unity.sg2/Documentation~/previews/ImposterUV.md b/com.unity.sg2/Documentation~/previews/ImposterUV.md index ea310de3709..ceaf71d6c19 100644 --- a/com.unity.sg2/Documentation~/previews/ImposterUV.md +++ b/com.unity.sg2/Documentation~/previews/ImposterUV.md @@ -3,10 +3,12 @@ Calculates the billboard positon and the virtual UVs for sampling. ## Inputs **InPosition** - The postion in Object space. -**UV** - The UV coordinates of the mesh. +**In UV** - The UV coordinates of the mesh. **Frames** - The number of the imposter frames in each axis. -**Offset** - The offset value from the pivot. **Size** - The size of the imposter. +**Offset** - The offset value from the pivot. +**Frame Clipping Threshold** - The clamping value for the neighboring frames most useful when parallax mapping is enabled. +**Texel Size** - The texel size of the heightmap or the textures will be sampled in the Imposter Sample Node. **Height Map** - The height map texture to sample. **Sampler** - The texture sampler to use for sampling the texture. **Parallax** - Parallax strength. diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl index c92f7521359..4079bdd9247 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl @@ -136,8 +136,8 @@ float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) } //Calculate Vertex postion and UVs -void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, - in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, +void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in float imposterFrameClip, + in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in float4 mapTexelSize, out float3 outPos, out float4 outWeights, out float2 outUV0, out float2 outUV1, out float2 outUV2, out float4 outUVGrid) { float framesMinusOne = imposterFrames - 1; @@ -237,19 +237,36 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo float2 vp1uv = frame1grid + vUv1.xy; float2 vp2uv = frame2grid + vUv2.xy; + //vert pos + outPos = BillboardPos + imposterOffset; + + //frame size ->2048/12 = 170.6 + float frameSize = mapTexelSize.z / imposterFrames; + //actual texture size used -> 170*12 = 2040 + float actualTextureSize = floor(frameSize) * imposterFrames; + //the scalar -> 2048/2040 = 0.99609375 + float scalar = mapTexelSize.z / actualTextureSize; + + vp0uv *= scalar; + vp0uv *= scalar; + vp0uv *= scalar; + if (parallax != 0) { float h0 = SAMPLE_TEXTURE2D(heightMap, ss, vp0uv)[heightMapChannel]; - float h1 = SAMPLE_TEXTURE2D(heightMap, ss, vp0uv)[heightMapChannel]; - float h2 = SAMPLE_TEXTURE2D(heightMap, ss, vp0uv)[heightMapChannel]; + float h1 = SAMPLE_TEXTURE2D(heightMap, ss, vp1uv)[heightMapChannel]; + float h2 = SAMPLE_TEXTURE2D(heightMap, ss, vp2uv)[heightMapChannel]; vp0uv += (0.5 - h0) * frame0local.xy * parallax; vp1uv += (0.5 - h1) * frame1local.xy * parallax; vp2uv += (0.5 - h2) * frame2local.xy * parallax; } - - //vert pos - outPos = BillboardPos + imposterOffset; + //clip out neighboring frames + float2 gridSize = 1.0 / imposterFrames.xx; + float2 bleeds = mapTexelSize.xy * imposterFrameClip; + vp0uv = clamp(vp0uv, frame0grid - bleeds, frame0grid + gridSize + bleeds); + vp1uv = clamp(vp1uv, frame1grid - bleeds, frame1grid + gridSize + bleeds); + vp2uv = clamp(vp2uv, frame2grid - bleeds, frame2grid + gridSize + bleeds); //surface outUV0 = vp0uv; @@ -259,9 +276,10 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo outUVGrid.xy = UVscaled; outUVGrid.zw = grid; } -void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, - in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, - out float3 outPos, out float2 outUV0, out float4 outUVGrid) + +void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in float imposterFrameClip, + in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in float4 mapTexelSize, + out float3 outPos, out float4 outWeights, out float2 outUV0, out float4 outUVGrid) { float framesMinusOne = imposterFrames - 1; @@ -321,24 +339,9 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame float2 frame0grid = gridSnap; float2 vp0uv = frame0grid + vUv0.xy; - if (parallax != 0) { - float h0 = SAMPLE_TEXTURE2D(heightMap, ss, vp0uv)[heightMapChannel]; - vp0uv += (0.5 - h0) * frame0local.xy * parallax; - } - //vert pos outPos = BillboardPos + imposterOffset; - //surface - outUV0 = vp0uv; - outUVGrid.xy = UVscaled; - outUVGrid.zw = grid; - -} -//Sample from UVs -void ImposterSample(in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, in float4 weights, in float imposterFrameClip, in float4 inUVGrid, - in float2 inUV0, in float2 inUV1, in float2 inUV2, in SamplerState ss, out float4 outColor) -{ //frame size ->2048/12 = 170.6 float frameSize = mapTexelSize.z / imposterFrames; //actual texture size used -> 170*12 = 2040 @@ -346,47 +349,36 @@ void ImposterSample(in float imposterFrames, in texture2D Texture, in float4 map //the scalar -> 2048/2040 = 0.99609375 float scalar = mapTexelSize.z / actualTextureSize; - inUV0 *= scalar; - inUV1 *= scalar; - inUV2 *= scalar; + vp0uv *= scalar; - float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; - float2 frame0grid = gridSnap; - float2 frame1grid = gridSnap + (lerp(float2(0, 1), float2(1, 0), weights.w) / imposterFrames.xx); - float2 frame2grid = gridSnap + (float2(1, 1) / imposterFrames.xx); + if (parallax != 0) { + float h0 = SAMPLE_TEXTURE2D(heightMap, ss, vp0uv)[heightMapChannel]; + vp0uv += (0.5 - h0) * frame0local.xy * parallax; + } //clip out neighboring frames float2 gridSize = 1.0 / imposterFrames.xx; float2 bleeds = mapTexelSize.xy * imposterFrameClip; - inUV0 = clamp(inUV0, frame0grid - bleeds, frame0grid + gridSize + bleeds); - inUV1 = clamp(inUV1, frame1grid - bleeds, frame1grid + gridSize + bleeds); - inUV2 = clamp(inUV2, frame2grid - bleeds, frame2grid + gridSize + bleeds); + vp0uv = clamp(vp0uv, frame0grid - bleeds, frame0grid + gridSize + bleeds); + //surface + outUV0 = vp0uv; + outUVGrid.xy = UVscaled; + outUVGrid.zw = grid; + +} +//Sample from UVs and blend bases on the weights +void ImposterSample(in texture2D Texture, in float4 weights, in float4 inUVGrid, + in float2 inUV0, in float2 inUV1, in float2 inUV2, in SamplerState ss, out float4 outColor) +{ outColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV0, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.x + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV1, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.y + SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV2, ddx(inUVGrid.xy), ddy(inUVGrid.xy)) * weights.z; } -void ImposterSample_oneFrame(in float imposterFrames, in texture2D Texture, in float4 mapTexelSize, in float imposterFrameClip, in float4 inUVGrid, +void ImposterSample_oneFrame(in texture2D Texture, in float4 inUVGrid, in float2 inUV0, in SamplerState ss, out float4 outColor) { - //frame size ->2048/12 = 170.6 - float frameSize = mapTexelSize.z / imposterFrames; - //actual texture size used -> 170*12 = 2040 - float actualTextureSize = floor(frameSize) * imposterFrames; - //the scalar -> 2048/2040 = 0.99609375 - float scalar = mapTexelSize.z / actualTextureSize; - - inUV0 *= scalar; - - float2 gridSnap = floor(inUVGrid.zw) / imposterFrames.xx; - float2 frame0grid = gridSnap; - - //clip out neighboring frames - float2 gridSize = 1.0 / imposterFrames.xx; - float2 bleeds = mapTexelSize.xy * imposterFrameClip; - inUV0 = clamp(inUV0, frame0grid - bleeds, frame0grid + gridSize + bleeds); - outColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV0, ddx(inUVGrid.xy), ddy(inUVGrid.xy)); } diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs index 257a09bfa0c..6821c25478c 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs @@ -14,7 +14,7 @@ internal class ImposterSampleNode : IStandardNode functions: new FunctionDescriptor[] { new( "ThreeFrames", - @"ImposterSample( Frames, Texture.tex, Texture.texelSize, Weights, Clip, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); + @"ImposterSample( Texture.tex, Weights, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); RGB = RGBA.rgb; R = RGBA.r; G = RGBA.g; @@ -25,19 +25,17 @@ internal class ImposterSampleNode : IStandardNode { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), - new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), - new ParameterDescriptor("UV1", TYPE.Vec4, Usage.In), - new ParameterDescriptor("UV2", TYPE.Vec4, Usage.In), + new ParameterDescriptor("UV0", TYPE.Vec2, Usage.In), + new ParameterDescriptor("UV1", TYPE.Vec2, Usage.In), + new ParameterDescriptor("UV2", TYPE.Vec2, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), - new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), - new ParameterDescriptor("Clip", TYPE.Float, Usage.Static, new float[] {0.1f}), new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out), new ParameterDescriptor("RGB", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("R", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("G", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("B", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("A", TYPE.Vec3, Usage.Out) + new ParameterDescriptor("R", TYPE.Float, Usage.Out), + new ParameterDescriptor("G", TYPE.Float, Usage.Out), + new ParameterDescriptor("B", TYPE.Float, Usage.Out), + new ParameterDescriptor("A", TYPE.Float, Usage.Out) }, new string[] { @@ -46,7 +44,7 @@ internal class ImposterSampleNode : IStandardNode ), new( "OneFrame",//TODO: change back to one frame - @"ImposterSample_oneFrame (Frames, Texture.tex, Texture.texelSize, Clip, Grid, UV0, Sampler.samplerstate, RGBA); + @"ImposterSample_oneFrame ( Texture.tex, Grid, UV0, Sampler.samplerstate, RGBA); RGB = RGBA.rgb; R = RGBA.r; G = RGBA.g; @@ -57,17 +55,14 @@ internal class ImposterSampleNode : IStandardNode { new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), - new ParameterDescriptor("UV0", TYPE.Vec4, Usage.In), + new ParameterDescriptor("UV0", TYPE.Vec2, Usage.In), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), - new ParameterDescriptor("Weights", TYPE.Vec4, Usage.In), - new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), - new ParameterDescriptor("Clip", TYPE.Float, Usage.Static, new float[] {0.1f}), new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out), new ParameterDescriptor("RGB", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("R", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("G", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("B", TYPE.Vec3, Usage.Out), - new ParameterDescriptor("A", TYPE.Vec3, Usage.Out) }, + new ParameterDescriptor("R", TYPE.Float, Usage.Out), + new ParameterDescriptor("G", TYPE.Float, Usage.Out), + new ParameterDescriptor("B", TYPE.Float, Usage.Out), + new ParameterDescriptor("A", TYPE.Float, Usage.Out) }, new string[] { "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl\"" @@ -81,7 +76,7 @@ internal class ImposterSampleNode : IStandardNode Name, displayName: "Imposter Sample", tooltip: "Samples from the three virtual UVs and blends them base on the camera intersection point to get the correct result.", - category: "Input/Mesh Deformation", + category: "Utility", hasPreview: false, description: "pkg://Documentation~/previews/ImposterSample.md", synonyms: new string[] { "billboard" }, @@ -116,19 +111,10 @@ internal class ImposterSampleNode : IStandardNode name: "Grid", tooltip: "The current UV grid" ), - new ParameterUIDescriptor( - name: "Frames", - tooltip: "The amount of the imposter frames" - ), new ParameterUIDescriptor( name: "Weights", tooltip: "Blending weights for three frames" ), - new ParameterUIDescriptor( - name: "Clip", - displayName:"Imposter Frame Clip", - tooltip: "The value to clamp between imposter frame. Useful when doing parallax mapping." - ), new ParameterUIDescriptor( name: "RGBA", tooltip: "A vector4 from the sampled texture" diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs index 6c43f4a279e..e4f498e22d5 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs @@ -14,20 +14,22 @@ internal class ImposterUVNode : IStandardNode functions: new FunctionDescriptor[] { new( "ThreeFrames", -" ImposterUV(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, HeightMapChannel, " + - " Sampler.samplerstate, Texture.tex, OutPos, Weights, UV0, UV1, UV2, Grid);", +" ImposterUV(Pos, inUV, Frames, Offset, Size, FrameClip, HemiSphere, Parallax, HeightMapChannel, " + + " Sampler.samplerstate, Texture.tex, TexelSize, OutPos, Weights, UV0, UV1, UV2, Grid);", new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), - new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), - new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), - new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), - new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), + new ParameterDescriptor("FrameClip", TYPE.Float, Usage.In), + new ParameterDescriptor("TexelSize", TYPE.Vec4, Usage.In), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), + new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), + new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3),//TODO: this one should be a dropdown with r/g/b/a chnnal options like Parallax Mapping node new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), new ParameterDescriptor("UV0", TYPE.Vec2, Usage.Out), new ParameterDescriptor("UV1", TYPE.Vec2, Usage.Out), @@ -41,20 +43,22 @@ internal class ImposterUVNode : IStandardNode } ),new( "OneFrame", -" ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, HemiSphere, Parallax, HeightMapChannel, " + - " Sampler.samplerstate, Texture.tex, OutPos, UV0, Grid);", +" ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, FrameClip, HemiSphere, Parallax, HeightMapChannel, " + + " Sampler.samplerstate, Texture.tex, TexelSize, OutPos, UV0, Grid);", new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), - new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), - new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), - new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), - new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3), new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), + new ParameterDescriptor("FrameClip", TYPE.Float, Usage.In), + new ParameterDescriptor("TexelSize", TYPE.Vec4, Usage.In), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), + new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), + new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), + new ParameterDescriptor("Sampler", TYPE.SamplerState, Usage.In), + new ParameterDescriptor("HeightMapChannel", TYPE.Int, Usage.In, 3),//TODO: this one should be a dropdown with r/g/b/a chnnal options like Parallax Mapping node new ParameterDescriptor("OutPos", TYPE.Vec3, Usage.Out), new ParameterDescriptor("UV0", TYPE.Vec2, Usage.Out), new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out) @@ -72,7 +76,7 @@ internal class ImposterUVNode : IStandardNode Name, displayName: "Imposter UV", tooltip: "Calculates the billboard positon and the virtual UVs for sampling.", - category: "Input/Mesh Deformation", + category: "Utility", hasPreview: false, description: "pkg://Documentation~/previews/ImposterUV.md", synonyms: new string[] { "billboard" }, @@ -103,6 +107,16 @@ internal class ImposterUVNode : IStandardNode name: "Offest", tooltip: "The offset value from the origin vertex positon" ), + new ParameterUIDescriptor( + name: "FrameClip", + displayName:"Frame Clipping Threshold", + tooltip: "The value to clamp between imposter frame. Useful when doing parallax mapping." + ), + new ParameterUIDescriptor( + name: "TexelSize", + displayName:"Texel Size", + tooltip: "The texel size of the sampling texture." + ), new ParameterUIDescriptor( name: "Size", tooltip: "The size of the imposter" From 9fd2d13b174e13918f5bc7e45e68f9e96dc44cde Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Wed, 26 Apr 2023 15:10:50 -0700 Subject: [PATCH 17/20] changed texel size to texture resolution --- .../Documentation~/Imposter-UV-Node.md | 6 ++-- .../Documentation~/previews/ImposterUV.md | 2 +- .../StandardDefinitions/Utility/Imposter.hlsl | 30 ++++++------------- .../Utility/ImposterUVNode.cs | 14 ++++----- 4 files changed, 20 insertions(+), 32 deletions(-) diff --git a/com.unity.sg2/Documentation~/Imposter-UV-Node.md b/com.unity.sg2/Documentation~/Imposter-UV-Node.md index 5beee1f05b4..13a032ffa69 100644 --- a/com.unity.sg2/Documentation~/Imposter-UV-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-UV-Node.md @@ -13,7 +13,7 @@ The Imposter UV Node calculates the billboard position and the UV coordinates ne | Size | Input | Float | The size of the imposter | | Offset | Input | Float | The offset value from the pivot | | Frame Clipping Threshold | Input | Float | The clamping value for the neighboring frames most useful when parallax mapping is enabled | -| Texel Size | Input | Vector4 | The texel size of the heightmap or the textures will be sampled in the Imposter Sample Node. | +| Texture Size | Input | Float | The resolution of the texture. | | HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type.This is Useful if the imposter object will only be seen from above | | Parallax | Input | Float | Parallax strength, if it equals to 0 than he parallax related control won't affect the outputs.| | Height map | Input | Texture2D | The height map texture to sample | @@ -63,11 +63,11 @@ The Imposter UV Node [!include[nodes-controls](./snippets/nodes-controls.md)] ### ThreeFrames ``` -ImposterUV(Pos, inUV, Frames, Offset, Size, imposterFrameClip, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, TexelSize, OutPos, Weights, Grid, UV0, UV1, UV2) +ImposterUV(Pos, inUV, Frames, Offset, Size, imposterFrameClip, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, TextureSize, OutPos, Weights, Grid, UV0, UV1, UV2) ``` ### OneFrame ``` -ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, imposterFrameClip, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, TexelSize, OutPos, Grid, UV0); +ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, imposterFrameClip, HemiSphere, Parallax, HeightMapChannel, ss, HeightMap, TextureSize, OutPos, Grid, UV0); ``` diff --git a/com.unity.sg2/Documentation~/previews/ImposterUV.md b/com.unity.sg2/Documentation~/previews/ImposterUV.md index ceaf71d6c19..d6cd306c751 100644 --- a/com.unity.sg2/Documentation~/previews/ImposterUV.md +++ b/com.unity.sg2/Documentation~/previews/ImposterUV.md @@ -8,7 +8,7 @@ Calculates the billboard positon and the virtual UVs for sampling. **Size** - The size of the imposter. **Offset** - The offset value from the pivot. **Frame Clipping Threshold** - The clamping value for the neighboring frames most useful when parallax mapping is enabled. -**Texel Size** - The texel size of the heightmap or the textures will be sampled in the Imposter Sample Node. +**Texture Size** - The texture resolution. **Height Map** - The height map texture to sample. **Sampler** - The texture sampler to use for sampling the texture. **Parallax** - Parallax strength. diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl index 4079bdd9247..27e896cf018 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl @@ -106,16 +106,10 @@ float2 PlaneIntersectionUV(float3 planeNormal, float3 planeX, float3 planeZ, flo float2 uv = float2(0, 0); if (planeDistance > 0) - { uv = -float2(dx, dz); - } - else - { - uv = float2(0, 0); - } uv /= UVscale; - uv += float2(0.5, 0.5); + uv += 0.5; return uv; } @@ -137,7 +131,7 @@ float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) //Calculate Vertex postion and UVs void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in float imposterFrameClip, - in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in float4 mapTexelSize, + in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in float TextureSize, out float3 outPos, out float4 outWeights, out float2 outUV0, out float2 outUV1, out float2 outUV2, out float4 outUVGrid) { float framesMinusOne = imposterFrames - 1; @@ -240,12 +234,9 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo //vert pos outPos = BillboardPos + imposterOffset; - //frame size ->2048/12 = 170.6 - float frameSize = mapTexelSize.z / imposterFrames; - //actual texture size used -> 170*12 = 2040 + float frameSize = TextureSize / imposterFrames; float actualTextureSize = floor(frameSize) * imposterFrames; - //the scalar -> 2048/2040 = 0.99609375 - float scalar = mapTexelSize.z / actualTextureSize; + float scalar = TextureSize / actualTextureSize; vp0uv *= scalar; vp0uv *= scalar; @@ -263,7 +254,7 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo } //clip out neighboring frames float2 gridSize = 1.0 / imposterFrames.xx; - float2 bleeds = mapTexelSize.xy * imposterFrameClip; + float2 bleeds = imposterFrameClip/ TextureSize; vp0uv = clamp(vp0uv, frame0grid - bleeds, frame0grid + gridSize + bleeds); vp1uv = clamp(vp1uv, frame1grid - bleeds, frame1grid + gridSize + bleeds); vp2uv = clamp(vp2uv, frame2grid - bleeds, frame2grid + gridSize + bleeds); @@ -278,7 +269,7 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo } void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in float imposterFrameClip, - in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in float4 mapTexelSize, + in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in float4 TextureSize, out float3 outPos, out float4 outWeights, out float2 outUV0, out float4 outUVGrid) { float framesMinusOne = imposterFrames - 1; @@ -342,12 +333,9 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame //vert pos outPos = BillboardPos + imposterOffset; - //frame size ->2048/12 = 170.6 - float frameSize = mapTexelSize.z / imposterFrames; - //actual texture size used -> 170*12 = 2040 + float frameSize = TextureSize / imposterFrames; float actualTextureSize = floor(frameSize) * imposterFrames; - //the scalar -> 2048/2040 = 0.99609375 - float scalar = mapTexelSize.z / actualTextureSize; + float scalar = TextureSize / actualTextureSize; vp0uv *= scalar; @@ -358,7 +346,7 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame } //clip out neighboring frames float2 gridSize = 1.0 / imposterFrames.xx; - float2 bleeds = mapTexelSize.xy * imposterFrameClip; + float2 bleeds = imposterFrameClip/ TextureSize; vp0uv = clamp(vp0uv, frame0grid - bleeds, frame0grid + gridSize + bleeds); //surface diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs index e4f498e22d5..5f21f1b9ed3 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs @@ -15,7 +15,7 @@ internal class ImposterUVNode : IStandardNode new( "ThreeFrames", " ImposterUV(Pos, inUV, Frames, Offset, Size, FrameClip, HemiSphere, Parallax, HeightMapChannel, " + - " Sampler.samplerstate, Texture.tex, TexelSize, OutPos, Weights, UV0, UV1, UV2, Grid);", + " Sampler.samplerstate, Texture.tex, TextureSize, OutPos, Weights, UV0, UV1, UV2, Grid);", new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), @@ -24,7 +24,7 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("FrameClip", TYPE.Float, Usage.In), - new ParameterDescriptor("TexelSize", TYPE.Vec4, Usage.In), + new ParameterDescriptor("TextureSize", TYPE.Float, Usage.In, new float[]{ 1024}), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), @@ -44,7 +44,7 @@ internal class ImposterUVNode : IStandardNode ),new( "OneFrame", " ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, FrameClip, HemiSphere, Parallax, HeightMapChannel, " + - " Sampler.samplerstate, Texture.tex, TexelSize, OutPos, UV0, Grid);", + " Sampler.samplerstate, Texture.tex, TextureSize, OutPos, UV0, Grid);", new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), @@ -53,7 +53,7 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("FrameClip", TYPE.Float, Usage.In), - new ParameterDescriptor("TexelSize", TYPE.Vec4, Usage.In), + new ParameterDescriptor("TextureSize", TYPE.Float, Usage.In, new float[]{ 1024}), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), @@ -113,9 +113,9 @@ internal class ImposterUVNode : IStandardNode tooltip: "The value to clamp between imposter frame. Useful when doing parallax mapping." ), new ParameterUIDescriptor( - name: "TexelSize", - displayName:"Texel Size", - tooltip: "The texel size of the sampling texture." + name: "TextureSize", + displayName:"Texture Size", + tooltip: "The resolution of the sampling texture." ), new ParameterUIDescriptor( name: "Size", From 8920dcf7ea192180d349e18cd64896e3d0386a8b Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 27 Apr 2023 14:19:41 -0700 Subject: [PATCH 18/20] fix typo --- com.unity.sg2/Documentation~/Imposter-Sample-Node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md index 1303df58cd4..c030ea26254 100644 --- a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md @@ -16,7 +16,7 @@ If the imposter object has more than one texture to sample (e.g. color, normal, | UV2 | Input | Vector2 | The virtual UV for the third frame | | Grid | Input | Vector4 | The current UV grid, which is used to find the corresponding sample frames | | Weights | Input | Float | The blending values in between the slected three frames| -| RGBA | Output | Vector3 | A vector4 from the sampled texture | +| RGBA | Output | Vector4 | A vector4 from the sampled texture | | RGB | Output | Vector3 | A vector3 from the sampled texture | | R | Output | Float | The r channel of the sampled texture | | G | Output | Float | The g channel of the sampled texture | From fadeda1a37e2db2a2d62cba4de89fa9f8f7d277c Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 27 Apr 2023 16:04:10 -0700 Subject: [PATCH 19/20] tweaks based on Ben's feedback --- .../Documentation~/Imposter-Sample-Node.md | 2 +- .../Documentation~/Imposter-UV-Node.md | 10 +++++----- .../StandardDefinitions/Utility/Imposter.hlsl | 20 +++++++++---------- .../Utility/ImposterSampleNode.cs | 20 +++++++++++++++++++ .../Utility/ImposterUVNode.cs | 14 ++++++------- 5 files changed, 43 insertions(+), 23 deletions(-) diff --git a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md index c030ea26254..7430b1e0f47 100644 --- a/com.unity.sg2/Documentation~/Imposter-Sample-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md @@ -15,7 +15,7 @@ If the imposter object has more than one texture to sample (e.g. color, normal, | UV1 | Input | Vector2 | The virtual UV for the second frame | | UV2 | Input | Vector2 | The virtual UV for the third frame | | Grid | Input | Vector4 | The current UV grid, which is used to find the corresponding sample frames | -| Weights | Input | Float | The blending values in between the slected three frames| +| Weights | Input | Vector4 | The blending values in between the slected three frames| | RGBA | Output | Vector4 | A vector4 from the sampled texture | | RGB | Output | Vector3 | A vector3 from the sampled texture | | R | Output | Float | The r channel of the sampled texture | diff --git a/com.unity.sg2/Documentation~/Imposter-UV-Node.md b/com.unity.sg2/Documentation~/Imposter-UV-Node.md index 13a032ffa69..df85e6692dc 100644 --- a/com.unity.sg2/Documentation~/Imposter-UV-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-UV-Node.md @@ -8,17 +8,17 @@ The Imposter UV Node calculates the billboard position and the UV coordinates ne | Name | Direction | Type | Description | |:------------ |:-------------|:-----|:---| | In Position | Input | Vector3 | The postion in Object space | -| In UV | Input | Vector4 | The UV coordinates of the mesh | -| Frames | Input | Float | The number of the imposter frames in each axis| +| In UV | Input | Vector2 | The UV coordinates of the mesh | +| Frames | Input | Int | The number of the imposter frames in each axis| | Size | Input | Float | The size of the imposter | -| Offset | Input | Float | The offset value from the pivot | +| Offset | Input | Vector3 | The offset value from the pivot | | Frame Clipping Threshold | Input | Float | The clamping value for the neighboring frames most useful when parallax mapping is enabled | -| Texture Size | Input | Float | The resolution of the texture. | +| Texture Size | Input | Int | The resolution of the texture. | | HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type.This is Useful if the imposter object will only be seen from above | | Parallax | Input | Float | Parallax strength, if it equals to 0 than he parallax related control won't affect the outputs.| | Height map | Input | Texture2D | The height map texture to sample | | Sampler | Input | Sampler State | The texture sampler to use for sampling the texture | -| Height Map Channel | Input | Int | The channle of the height map to sample for parallax mapping, if any| +| Height Map Channel | Input | Int | The channel of the height map to sample for parallax mapping, if any| | Out Positon | Output | Vector3 | The output billboard position | | UV0 | Output | Vector2 | The virtual UV for the base frame | | UV1 | Output | Vector2 | The virtual UV for the second frame | diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl index 27e896cf018..40113ae6fdc 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl @@ -130,8 +130,8 @@ float3 CalculateBillboardProjection(float3 objectSpaceCameraDir, float2 uv) } //Calculate Vertex postion and UVs -void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in float imposterFrameClip, - in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in float TextureSize, +void ImposterUV(in float3 inPos, in float2 inUV, in int imposterFrames, in float3 imposterOffset, in float imposterSize, in float imposterFrameClip, + in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in int TextureSize, out float3 outPos, out float4 outWeights, out float2 outUV0, out float2 outUV1, out float2 outUV2, out float4 outUVGrid) { float framesMinusOne = imposterFrames - 1; @@ -141,10 +141,10 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); //get uv in a single frame - float2 UVscaled = inUV.xy * (1.0 / imposterFrames); + float2 UVscaled = inUV * (1.0 / imposterFrames); float2 size = imposterSize.xx * 1.33; - float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV); BillboardPos *= 0.67; //camera to projection vector @@ -268,9 +268,9 @@ void ImposterUV(in float3 inPos, in float4 inUV, in float imposterFrames, in flo outUVGrid.zw = grid; } -void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrames, in float3 imposterOffset, in float imposterSize, in float imposterFrameClip, - in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in float4 TextureSize, - out float3 outPos, out float4 outWeights, out float2 outUV0, out float4 outUVGrid) +void ImposterUV_oneFrame(in float3 inPos, in float2 inUV, in int imposterFrames, in float3 imposterOffset, in float imposterSize, in float imposterFrameClip, + in bool isHemi, in float parallax, in int heightMapChannel, in SamplerState ss, in Texture2D heightMap, in int TextureSize, + out float3 outPos, out float2 outUV0, out float4 outUVGrid) { float framesMinusOne = imposterFrames - 1; @@ -279,10 +279,10 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame float3 objectSpaceCameraDir = normalize(objectSpaceCameraPos.xyz); //get uv in a single frame - float2 UVscaled = inUV.xy * (1.0 / imposterFrames); + float2 UVscaled = inUV * (1.0 / imposterFrames); float2 size = imposterSize.xx * 1.33; - float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV.xy); + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV); BillboardPos *= 0.67; //camera to projection vector @@ -346,7 +346,7 @@ void ImposterUV_oneFrame(in float3 inPos, in float4 inUV, in float imposterFrame } //clip out neighboring frames float2 gridSize = 1.0 / imposterFrames.xx; - float2 bleeds = imposterFrameClip/ TextureSize; + float2 bleeds = imposterFrameClip / TextureSize; vp0uv = clamp(vp0uv, frame0grid - bleeds, frame0grid + gridSize + bleeds); //surface diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs index 6821c25478c..2e9bb7bdc85 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs @@ -118,6 +118,26 @@ internal class ImposterSampleNode : IStandardNode new ParameterUIDescriptor( name: "RGBA", tooltip: "A vector4 from the sampled texture" + ), + new ParameterUIDescriptor( + name: "RGB", + tooltip: "A vector3 from the sampled texture" + ), + new ParameterUIDescriptor( + name: "R", + tooltip: "The red channel of the sampled texture" + ), + new ParameterUIDescriptor( + name: "G", + tooltip: "The green channel of the sampled texture" + ), + new ParameterUIDescriptor( + name: "B", + tooltip: "The blue channel of the sampled texture" + ), + new ParameterUIDescriptor( + name: "A", + tooltip: "The alpha channel of the sampled texture" ) } ); diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs index 5f21f1b9ed3..29d62537e11 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs @@ -19,12 +19,12 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), - new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), - new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), + new ParameterDescriptor("inUV", TYPE.Vec2, Usage.In, REF.UV0), + new ParameterDescriptor("Frames", TYPE.Int, Usage.In, new float[] {16}), new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("FrameClip", TYPE.Float, Usage.In), - new ParameterDescriptor("TextureSize", TYPE.Float, Usage.In, new float[]{ 1024}), + new ParameterDescriptor("TextureSize", TYPE.Int, Usage.In, new float[]{ 1024}), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), @@ -48,12 +48,12 @@ internal class ImposterUVNode : IStandardNode new ParameterDescriptor[] { new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), - new ParameterDescriptor("inUV", TYPE.Vec4, Usage.In, REF.UV0), - new ParameterDescriptor("Frames", TYPE.Float, Usage.In, new float[] {16f}), + new ParameterDescriptor("inUV", TYPE.Vec2, Usage.In, REF.UV0), + new ParameterDescriptor("Frames", TYPE.Int, Usage.In, new float[] {16}), new ParameterDescriptor("Size", TYPE.Float, Usage.In, new float[] {1}), new ParameterDescriptor("Offset", TYPE.Vec3, Usage.In), new ParameterDescriptor("FrameClip", TYPE.Float, Usage.In), - new ParameterDescriptor("TextureSize", TYPE.Float, Usage.In, new float[]{ 1024}), + new ParameterDescriptor("TextureSize", TYPE.Int, Usage.In, new float[]{ 1024}), new ParameterDescriptor("HemiSphere", TYPE.Bool, Usage.In), new ParameterDescriptor("Parallax", TYPE.Float, Usage.In), new ParameterDescriptor("Texture", TYPE.Texture2D, Usage.In), @@ -136,7 +136,7 @@ internal class ImposterUVNode : IStandardNode ), new ParameterUIDescriptor( name: "Parallax", - tooltip: "Adds parallax effect the port value is true" + tooltip: "Adds a parallax effect if the port value is greater than zero" ), new ParameterUIDescriptor( name: "HeightMapChannel", From 2ba3f7dba51cae7931ee5d9985bd9504ed44d852 Mon Sep 17 00:00:00 2001 From: Tracy Chen Date: Thu, 27 Apr 2023 17:00:12 -0700 Subject: [PATCH 20/20] fix typos --- com.unity.sg2/Documentation~/Imposter-UV-Node.md | 6 +++--- com.unity.sg2/Documentation~/previews/ImposterUV.md | 6 +++--- .../StandardDefinitions/Utility/ImposterUVNode.cs | 7 ++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/com.unity.sg2/Documentation~/Imposter-UV-Node.md b/com.unity.sg2/Documentation~/Imposter-UV-Node.md index df85e6692dc..7482977f3af 100644 --- a/com.unity.sg2/Documentation~/Imposter-UV-Node.md +++ b/com.unity.sg2/Documentation~/Imposter-UV-Node.md @@ -14,11 +14,11 @@ The Imposter UV Node calculates the billboard position and the UV coordinates ne | Offset | Input | Vector3 | The offset value from the pivot | | Frame Clipping Threshold | Input | Float | The clamping value for the neighboring frames most useful when parallax mapping is enabled | | Texture Size | Input | Int | The resolution of the texture. | -| HemiSphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type.This is Useful if the imposter object will only be seen from above | +| Hemisphere | Input | Boolean | If it's true, calculates the imposter grid and UVs base on hemisphere type.This is Useful if the imposter object will only be seen from above | | Parallax | Input | Float | Parallax strength, if it equals to 0 than he parallax related control won't affect the outputs.| | Height map | Input | Texture2D | The height map texture to sample | -| Sampler | Input | Sampler State | The texture sampler to use for sampling the texture | -| Height Map Channel | Input | Int | The channel of the height map to sample for parallax mapping, if any| +| Heightmap Sampler | Input | Sampler State | The texture sampler to use for sampling the texture | +| Heightmap Smaple Channel | Input | Int | The channel of the height map to sample for parallax mapping, if any| | Out Positon | Output | Vector3 | The output billboard position | | UV0 | Output | Vector2 | The virtual UV for the base frame | | UV1 | Output | Vector2 | The virtual UV for the second frame | diff --git a/com.unity.sg2/Documentation~/previews/ImposterUV.md b/com.unity.sg2/Documentation~/previews/ImposterUV.md index d6cd306c751..6b52e9a33d7 100644 --- a/com.unity.sg2/Documentation~/previews/ImposterUV.md +++ b/com.unity.sg2/Documentation~/previews/ImposterUV.md @@ -9,10 +9,10 @@ Calculates the billboard positon and the virtual UVs for sampling. **Offset** - The offset value from the pivot. **Frame Clipping Threshold** - The clamping value for the neighboring frames most useful when parallax mapping is enabled. **Texture Size** - The texture resolution. -**Height Map** - The height map texture to sample. -**Sampler** - The texture sampler to use for sampling the texture. +**Heightmap** - The height map texture to sample. +**Heightmap Sampler** - The texture sampler to use for sampling the texture. **Parallax** - Parallax strength. -**Height Map Channel** - The channle of the height map to sample for parallax mapping, if any. +**Heightmap Sample Channel** - The channle of the height map to sample for parallax mapping, if any. **HemiSphere** - If it's true, calculates the imposter grid and UVs base on hemisphere type. Useful if the object is only seen from above. ## Output diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs index 29d62537e11..f54f451866e 100644 --- a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs @@ -122,16 +122,17 @@ internal class ImposterUVNode : IStandardNode tooltip: "The size of the imposter" ), new ParameterUIDescriptor( - name: "HemiSphere", + name: "Hemisphere", tooltip: "If it's true, calculate imposter grid and UVs base on hemisphere type." ), new ParameterUIDescriptor( name: "Texture", - displayName:"Height Map", + displayName:"Heightmap", tooltip: "The texture asset to sample" ), new ParameterUIDescriptor( name: "Sampler", + displayName:"Heightmap Sampler", tooltip: "The texture sampler to use for sampling the texture" ), new ParameterUIDescriptor( @@ -140,7 +141,7 @@ internal class ImposterUVNode : IStandardNode ), new ParameterUIDescriptor( name: "HeightMapChannel", - displayName:"Heigh Map Channel", + displayName:"Heighmap Sample Channel", tooltip: "The texture channel to sample from for the parallax effect" ), new ParameterUIDescriptor(