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..7430b1e0f47 --- /dev/null +++ b/com.unity.sg2/Documentation~/Imposter-Sample-Node.md @@ -0,0 +1,69 @@ +# Imposter Sample Node + +## Description + +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 | +|:------------ |:-------------|:-----|:---| +| Texture | Input | Texture2D | The texture asset to sample | +| Sampler | Input | Sampler State | The texture sampler to use for sampling the texture | +| 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 | +| 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 | +| 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 + +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. UV1, UV2 and Weights inputs won't be shown.
+ +## 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( Texture.tex, TexelSize, Weights, Grid, UV0, UV1, UV2, Sampler.samplerstate, RGBA); +``` + +### OneFrame + +``` +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 new file mode 100644 index 00000000000..7482977f3af --- /dev/null +++ b/com.unity.sg2/Documentation~/Imposter-UV-Node.md @@ -0,0 +1,73 @@ +# Imposter UV Node + +## Description + +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 | +| 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 | 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 | +| 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 | +| 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 | +| 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 + +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. UV1, UV2 and Weights outputs won't be shown.
+ +## 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, 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, TextureSize, 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..244f4de87f2 --- /dev/null +++ b/com.unity.sg2/Documentation~/previews/ImposterSample.md @@ -0,0 +1,23 @@ +## Description +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. +**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. +**Weights** - The blending values in between the slected three 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. diff --git a/com.unity.sg2/Documentation~/previews/ImposterUV.md b/com.unity.sg2/Documentation~/previews/ImposterUV.md new file mode 100644 index 00000000000..6b52e9a33d7 --- /dev/null +++ b/com.unity.sg2/Documentation~/previews/ImposterUV.md @@ -0,0 +1,26 @@ +## Description +Calculates the billboard positon and the virtual UVs for sampling. + +## Inputs +**InPosition** - The postion in Object space. +**In UV** - The UV coordinates of the mesh. +**Frames** - The number of the imposter frames in each axis. +**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. +**Texture Size** - The texture resolution. +**Heightmap** - The height map texture to sample. +**Heightmap Sampler** - The texture sampler to use for sampling the texture. +**Parallax** - Parallax strength. +**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 +**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/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 diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl new file mode 100644 index 00000000000..40113ae6fdc --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl @@ -0,0 +1,373 @@ +#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; +} + +float4 CalculateWeights(float2 uv) +{ + uv = frac(uv); + + float2 oneMinusUV = 1 - uv.xy; + + float4 weights; + //frame 0 + weights.x = min(oneMinusUV.x, oneMinusUV.y); + //frame 1 + weights.y = abs(dot(uv, float2(1.0, -1.0))); + //frame 2 + weights.z = min(uv.x, uv.y); + //mask + weights.w = saturate(ceil(uv.x - uv.y)); + + return weights; +} + +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); + + uv /= UVscale; + uv += 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 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; + + //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 * (1.0 / imposterFrames); + float2 size = imposterSize.xx * 1.33; + + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV); + 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 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)); + + 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; + + 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; + + //vert pos + outPos = BillboardPos + imposterOffset; + + float frameSize = TextureSize / imposterFrames; + float actualTextureSize = floor(frameSize) * imposterFrames; + float scalar = TextureSize / actualTextureSize; + + vp0uv *= scalar; + vp0uv *= scalar; + vp0uv *= scalar; + + if (parallax != 0) { + + float h0 = 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; + } + //clip out neighboring frames + float2 gridSize = 1.0 / imposterFrames.xx; + 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); + + //surface + outUV0 = vp0uv; + outUV1 = vp1uv; + outUV2 = vp2uv; + outWeights = weights; + outUVGrid.xy = UVscaled; + outUVGrid.zw = grid; +} + +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; + + //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 * (1.0 / imposterFrames); + float2 size = imposterSize.xx * 1.33; + + float3 BillboardPos = CalculateBillboardProjection(objectSpaceCameraDir, inUV); + 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); + + //convert frame coord to octahedron ray + float3 frame0ray = normalize(GridToVector(float2(gridFloor / 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; + + float2 gridSnap = floor(grid) / imposterFrames.xx; + float2 frame0grid = gridSnap; + float2 vp0uv = frame0grid + vUv0.xy; + + //vert pos + outPos = BillboardPos + imposterOffset; + + float frameSize = TextureSize / imposterFrames; + float actualTextureSize = floor(frameSize) * imposterFrames; + float scalar = TextureSize / actualTextureSize; + + vp0uv *= scalar; + + 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 = imposterFrameClip / TextureSize; + 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 texture2D Texture, in float4 inUVGrid, + in float2 inUV0, in SamplerState ss, out float4 outColor) +{ + outColor = SAMPLE_TEXTURE2D_GRAD(Texture, ss, inUV0, ddx(inUVGrid.xy), ddy(inUVGrid.xy)); +} + +#endif diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl.meta new file mode 100644 index 00000000000..6c340c1de4e --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/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/Utility/ImposterSampleNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs new file mode 100644 index 00000000000..2e9bb7bdc85 --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs @@ -0,0 +1,145 @@ +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( Texture.tex, Weights, 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.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("RGBA", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("RGB", 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\"" + } + ), + new( + "OneFrame",//TODO: change back to one frame + @"ImposterSample_oneFrame ( Texture.tex, 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.Vec2, Usage.In), + new ParameterDescriptor("Grid", TYPE.Vec4, Usage.In), + new ParameterDescriptor("RGBA", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("RGB", 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\"" + } + ) + } + ); + + 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: "Utility", + 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: "Weights", + tooltip: "Blending weights for three frames" + ), + 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/ImposterSampleNode.cs.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterSampleNode.cs.meta new file mode 100644 index 00000000000..8a706bbb5be --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/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/Utility/ImposterUVNode.cs b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs new file mode 100644 index 00000000000..f54f451866e --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs @@ -0,0 +1,175 @@ +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, FrameClip, HemiSphere, Parallax, HeightMapChannel, " + + " Sampler.samplerstate, Texture.tex, TextureSize, OutPos, Weights, UV0, UV1, UV2, Grid);", + new ParameterDescriptor[] + { + new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), + 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.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), + 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), + new ParameterDescriptor("UV2", TYPE.Vec2, Usage.Out), + new ParameterDescriptor("Grid", TYPE.Vec4, Usage.Out), + new ParameterDescriptor("Weights", TYPE.Vec4, Usage.Out) + }, + new string[] + { + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl\"" + } + ),new( + "OneFrame", +" ImposterUV_oneFrame(Pos, inUV, Frames, Offset, Size, FrameClip, HemiSphere, Parallax, HeightMapChannel, " + + " Sampler.samplerstate, Texture.tex, TextureSize, OutPos, UV0, Grid);", + new ParameterDescriptor[] + { + new ParameterDescriptor("Pos", TYPE.Vec3, Usage.In, REF.ObjectSpace_Position), + 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.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), + 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) + }, + new string[] + { + "\"Packages/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/Imposter.hlsl\"" + } + ) + } + ); + + public static NodeUIDescriptor NodeUIDescriptor => new( + Version, + Name, + displayName: "Imposter UV", + tooltip: "Calculates the billboard positon and the virtual UVs for sampling.", + category: "Utility", + 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", + options: REF.OptionList.Positions, + tooltip: "The postiont in Object space" + ), + new ParameterUIDescriptor( + name: "inUV", + displayName:"In UV", + options: REF.OptionList.UVs, + 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: "FrameClip", + displayName:"Frame Clipping Threshold", + tooltip: "The value to clamp between imposter frame. Useful when doing parallax mapping." + ), + new ParameterUIDescriptor( + name: "TextureSize", + displayName:"Texture Size", + tooltip: "The resolution of the sampling texture." + ), + 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: "Texture", + 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( + name: "Parallax", + tooltip: "Adds a parallax effect if the port value is greater than zero" + ), + new ParameterUIDescriptor( + name: "HeightMapChannel", + displayName:"Heighmap Sample Channel", + tooltip: "The texture channel to sample from for the parallax effect" + ), + 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: "Weights", + tooltip: "Blending weights for three frames" + ), + new ParameterUIDescriptor( + name: "Grid", + tooltip: "The current UV grid" + ) + } + ); + } +} diff --git a/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs.meta b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs.meta new file mode 100644 index 00000000000..f89ec0d890f --- /dev/null +++ b/com.unity.sg2/Editor/GraphDeltaRegistry/FunctionDefinitions/StandardDefinitions/Utility/ImposterUVNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 983c760811aff784b9ceb86980c5eb57 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: