Initialer Upload neues Unity-Projekt

This commit is contained in:
Daniel Ocks
2025-07-21 09:11:14 +02:00
commit eeca72985b
14558 changed files with 1508140 additions and 0 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2e12936d5396e634480523f2eb9bcbea
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections;
using UnityEngine;
namespace Oculus.Interaction.Demo
{
[RequireComponent(typeof(MeshFilter))]
public class MeshBlit : MonoBehaviour
{
private static int MAIN_TEX = Shader.PropertyToID("_MainTex");
public Material material;
public RenderTexture renderTexture;
[SerializeField]
private float _blitsPerSecond = -1;
public float BlitsPerSecond
{
get
{
return _blitsPerSecond;
}
set
{
SetBlitsPerSecond(value);
}
}
private Mesh _mesh;
private WaitForSeconds _waitForSeconds;
private Mesh Mesh => _mesh ? _mesh : _mesh = GetComponent<MeshFilter>().sharedMesh;
private void OnEnable()
{
SetBlitsPerSecond(_blitsPerSecond);
StartCoroutine(BlitRoutine());
IEnumerator BlitRoutine()
{
while (true)
{
yield return _waitForSeconds;
Blit();
}
}
}
public void Blit()
{
if (renderTexture == null)
{
throw new NullReferenceException("MeshBlit.Blit must have a RenderTexture assigned");
}
if (material == null)
{
throw new NullReferenceException("MeshBlit.Blit must have a Material assigned");
}
if (Mesh == null)
{
throw new NullReferenceException("MeshBlit.Blit's MeshFilter has no mesh");
}
RenderTexture temp = RenderTexture.GetTemporary(renderTexture.descriptor);
Graphics.Blit(renderTexture, temp);
material.SetTexture(MAIN_TEX, temp);
var previous = RenderTexture.active;
RenderTexture.active = renderTexture;
material.SetPass(0);
Graphics.DrawMeshNow(Mesh, transform.localToWorldMatrix);
RenderTexture.active = previous;
material.SetTexture(MAIN_TEX, null);
RenderTexture.ReleaseTemporary(temp);
}
private void SetBlitsPerSecond(float value)
{
_blitsPerSecond = value;
_waitForSeconds = value > 0 ? new WaitForSeconds(1 / _blitsPerSecond) : null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f38a2c2a6f2edf246a68b41b406dd964
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6d03fabf79ac272479773d0172fb4740
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,97 @@
fileFormatVersion: 2
guid: 06aafc7fcb186454893618a0b137089b
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 1
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
// @lint-ignore SOCIALVRTEXTUREIMPORTS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,88 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
Shader "MeshBlit/MeshBlitStamp"
{
Properties
{
[NoScaleOffset] _Stamp("Stamp", 2D) = "black" {}
_StampMultipler("Stamp Multipler", Float) = 1
[Enum(UV0,0,UV1,1)] _UV("UV Set", Float) = 1
[HideInInspector]_MainTex("Texture", 2D) = "black" {}
[HideInInspector]_Subtract("Subtract", float) = 0
}
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 normal : NORMAL;
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 stampUV : TEXCOORD1;
float3 normalWS : TEXCOORD4;
float4 vertex : SV_POSITION;
};
float4x4 _StampMatrix;
sampler2D _MainTex;
sampler2D _Stamp;
half _StampMultipler;
float _Subtract;
half _UV;
v2f vert(appdata v)
{
v2f o;
float2 uv = (_UV == 0) ? v.uv0 : v.uv1;
o.uv = uv;
#if SHADER_API_D3D11
uv.y = 1 - uv.y;
#endif
o.vertex = float4(uv * 2 - 1, 0.5, 1);
float4 positionWS = mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1));
o.stampUV = mul(_StampMatrix, positionWS);
o.normalWS = normalize(UnityObjectToWorldNormal(v.normal)); //TODO dont include the stamp on backfaces
return o;
}
half4 frag(v2f i) : SV_Target
{
float4 col = tex2D(_MainTex, i.uv);
col = max(0, col - _Subtract);
float2 stampUV = saturate((i.stampUV.xy / i.stampUV.w) * 0.5 + 0.5);
half4 stamp = tex2D(_Stamp, stampUV);
col += stamp * _StampMultipler;
col = saturate(col);
return col;
}
ENDCG
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 14c4f10921fa2ed46b4a9be3c07abeee
ShaderImporter:
externalObjects: {}
defaultTextures:
- _Stamp: {instanceID: 0}
- _MainTex: {instanceID: 0}
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,358 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Oculus.Interaction.HandGrab;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace Oculus.Interaction.Demo
{
public class WaterSpray : MonoBehaviour, IHandGrabUseDelegate
{
public enum NozzleMode
{
Spray,
Stream
}
[Header("Input")]
[SerializeField]
private Transform _trigger;
[SerializeField]
private Transform _nozzle;
[SerializeField]
private AnimationCurve _triggerRotationCurve;
[SerializeField]
private SnapAxis _axis = SnapAxis.X;
[SerializeField]
[Range(0f, 1f)]
private float _releaseThresold = 0.3f;
[SerializeField]
[Range(0f, 1f)]
private float _fireThresold = 0.9f;
[SerializeField]
private float _triggerSpeed = 3f;
[SerializeField]
private AnimationCurve _strengthCurve = AnimationCurve.EaseInOut(0f,0f,1f,1f);
[Header("Output")]
[SerializeField, Tooltip("Masks the Raycast used to find objects to make wet")]
private LayerMask _raycastLayerMask = ~0;
[SerializeField, Tooltip("The spread angle when spraying, larger values will make a larger area wet")]
private float _spraySpreadAngle = 40;
[SerializeField, Tooltip("The spread angle when using stream, larger values will make a larger area wet")]
private float _streamSpreadAngle = 4;
[SerializeField]
private float _sprayStrength = 1.5f;
[SerializeField]
private int _sprayHits = 6;
[SerializeField]
private float _sprayRandomness = 6f;
[SerializeField, Tooltip("The max distance of the spray, controls the raycast and shader")]
private float _maxDistance = 2;
[SerializeField]
private float _dryingSpeed = 0.1f;
[SerializeField, Tooltip("Material for applying a stamp, should using the MeshBlitStamp shader or similar")]
private Material _sprayStampMaterial = null;
[SerializeField, Tooltip("When not null, will be set as the '_WetBumpMap' property on wet renderers")]
private Texture _waterBumpOverride = null;
[SerializeField]
private UnityEvent WhenSpray;
[SerializeField]
private UnityEvent WhenStream;
private static readonly int WET_MAP_PROPERTY = Shader.PropertyToID("_WetMap");
private static readonly int STAMP_MULTIPLIER_PROPERTY = Shader.PropertyToID("_StampMultipler");
private static readonly int SUBTRACT_PROPERTY = Shader.PropertyToID("_Subtract");
private static readonly int WET_BUMPMAP_PROPERTY = Shader.PropertyToID("_WetBumpMap");
private static readonly int STAMP_MATRIX_PROPERTY = Shader.PropertyToID("_StampMatrix");
private static readonly WaitForSeconds WAIT_TIME = new WaitForSeconds(0.1f);
private bool _wasFired = false;
private float _dampedUseStrength = 0;
private float _lastUseTime;
#region input
private void SprayWater()
{
NozzleMode mode = GetNozzleMode();
if (mode == NozzleMode.Spray)
{
Spray();
WhenSpray?.Invoke();
}
else if (mode == NozzleMode.Stream)
{
Stream();
WhenStream?.Invoke();
}
}
private void UpdateTriggerRotation(float progress)
{
float value = _triggerRotationCurve.Evaluate(progress);
Vector3 angles = _trigger.localEulerAngles;
if ((_axis & SnapAxis.X) != 0)
{
angles.x = value;
}
if ((_axis & SnapAxis.Y) != 0)
{
angles.y = value;
}
if ((_axis & SnapAxis.Z) != 0)
{
angles.z = value;
}
_trigger.localEulerAngles = angles;
}
private NozzleMode GetNozzleMode()
{
int rotations = ((int)_nozzle.localEulerAngles.z + 45) / 90;
if (rotations % 2 == 0)
{
return NozzleMode.Spray;
}
return NozzleMode.Stream;
}
#endregion
#region output
private void Spray()
{
StartCoroutine(StampRoutine(_sprayHits, _sprayRandomness, _spraySpreadAngle, _sprayStrength));
}
private void Stream()
{
StartCoroutine(StampRoutine(_sprayHits, 0, _streamSpreadAngle, _sprayStrength));
}
private IEnumerator StampRoutine(int stampCount, float randomness, float spread, float strength)
{
StartStamping();
Pose originalPose = _nozzle.GetPose();
for (int i = 0; i < stampCount; i++)
{
yield return WAIT_TIME;
Pose randomPose = originalPose;
randomPose.rotation =
randomPose.rotation *
Quaternion.Euler(
Random.Range(-randomness, randomness),
Random.Range(-randomness, randomness),
0f);
Stamp(randomPose, _maxDistance, spread, strength);
}
StartDrying();
}
private void StartStamping()
{
_sprayStampMaterial.SetFloat(SUBTRACT_PROPERTY, 0);
}
private void StartDrying()
{
_sprayStampMaterial.SetMatrix(STAMP_MATRIX_PROPERTY, Matrix4x4.zero);
_sprayStampMaterial.SetFloat(SUBTRACT_PROPERTY, _dryingSpeed);
}
private void Stamp(Pose pose, float maxDistance, float angle, float strength)
{
_sprayStampMaterial.SetMatrix(STAMP_MATRIX_PROPERTY, CreateStampMatrix(pose, angle));
_sprayStampMaterial.SetFloat(STAMP_MULTIPLIER_PROPERTY, strength);
float radius = Mathf.Tan(Mathf.Deg2Rad * angle / 2) * maxDistance;
Vector3 startPoint = pose.position + pose.forward * radius;
Vector3 endPoint = pose.position + pose.forward * maxDistance;
int hitCount = Physics.OverlapCapsuleNonAlloc(startPoint, endPoint, radius, NonAlloc._overlapResults, _raycastLayerMask.value, QueryTriggerInteraction.Ignore);
HashSet<Transform> roots = NonAlloc.GetRootsFromOverlapResults(hitCount);
foreach (Transform rootObject in roots)
{
RenderSplash(rootObject);
}
roots.Clear();
}
/// <summary>
/// Finds Meshes that are part of the rootObject and blits the material on them
/// </summary>
private void RenderSplash(Transform rootObject)
{
List<MeshFilter> meshFilters = NonAlloc.GetMeshFiltersInChildren(rootObject);
for (int i = 0; i < meshFilters.Count; i++)
{
int id = meshFilters[i].GetInstanceID();
if (!NonAlloc._blits.ContainsKey(id)) { NonAlloc._blits[id] = CreateMeshBlit(meshFilters[i]); }
NonAlloc._blits[id].Blit();
}
}
/// <summary>
/// Sets up a new mesh blit on the mesh filter for the water spray
/// </summary>
private MeshBlit CreateMeshBlit(MeshFilter meshFilter)
{
MeshBlit newBlit = meshFilter.gameObject.AddComponent<MeshBlit>();
newBlit.material = _sprayStampMaterial;
newBlit.renderTexture = new RenderTexture(512, 512, 0, RenderTextureFormat.RHalf);
newBlit.BlitsPerSecond = 30;
if (meshFilter.TryGetComponent(out Renderer renderer))
{
renderer.GetPropertyBlock(NonAlloc.PropertyBlock);
NonAlloc.PropertyBlock.SetTexture(WET_MAP_PROPERTY, newBlit.renderTexture);
if (_waterBumpOverride)
{
NonAlloc.PropertyBlock.SetTexture(WET_BUMPMAP_PROPERTY, _waterBumpOverride);
}
renderer.SetPropertyBlock(NonAlloc.PropertyBlock);
}
return newBlit;
}
private Matrix4x4 CreateStampMatrix(Pose pose, float angle)
{
Matrix4x4 viewMatrix = Matrix4x4.TRS(pose.position, pose.rotation, Vector3.one).inverse;
viewMatrix.m20 *= -1f;
viewMatrix.m21 *= -1f;
viewMatrix.m22 *= -1f;
viewMatrix.m23 *= -1f;
return GL.GetGPUProjectionMatrix(Matrix4x4.Perspective(angle, 1, 0, _maxDistance), true) * viewMatrix;
}
/// <summary>
/// Cleans destroyed MeshBlits form the dictionary
/// </summary>
private void OnDestroy()
{
NonAlloc.CleanUpDestroyedBlits();
}
public void BeginUse()
{
_dampedUseStrength = 0f;
_lastUseTime = Time.realtimeSinceStartup;
}
public void EndUse()
{
}
public float ComputeUseStrength(float strength)
{
float delta = Time.realtimeSinceStartup - _lastUseTime;
_lastUseTime = Time.realtimeSinceStartup;
if (strength > _dampedUseStrength)
{
_dampedUseStrength = Mathf.Lerp(_dampedUseStrength, strength, _triggerSpeed * delta);
}
else
{
_dampedUseStrength = strength;
}
float progress = _strengthCurve.Evaluate(_dampedUseStrength);
UpdateTriggerProgress(progress);
return progress;
}
private void UpdateTriggerProgress(float progress)
{
UpdateTriggerRotation(progress);
if (progress >= _fireThresold && !_wasFired)
{
_wasFired = true;
SprayWater();
}
else if (progress <= _releaseThresold)
{
_wasFired = false;
}
}
#endregion
/// <summary>
/// Allocation helpers
/// </summary>
static class NonAlloc
{
public static readonly Collider[] _overlapResults = new Collider[12];
public static readonly Dictionary<int, MeshBlit> _blits = new Dictionary<int, MeshBlit>();
public static MaterialPropertyBlock PropertyBlock => _block != null ? _block : _block = new MaterialPropertyBlock();
private static readonly List<MeshFilter> _meshFilters = new List<MeshFilter>();
private static readonly HashSet<Transform> _roots = new HashSet<Transform>();
private static MaterialPropertyBlock _block;
public static List<MeshFilter> GetMeshFiltersInChildren(Transform root)
{
root.GetComponentsInChildren(_meshFilters);
return _meshFilters;
}
public static HashSet<Transform> GetRootsFromOverlapResults(int hitCount)
{
_roots.Clear();
for (int i = 0; i < hitCount; i++)
{
Transform root = GetRoot(_overlapResults[i]);
_roots.Add(root);
}
return _roots;
}
/// <summary>
/// Returns the most likely 'root object' for the hit e.g. the rigidbody
/// </summary>
static Transform GetRoot(Collider hit)
{
return hit.attachedRigidbody ? hit.attachedRigidbody.transform :
hit.transform.parent ? hit.transform.parent :
hit.transform;
}
public static void CleanUpDestroyedBlits()
{
if (!_blits.ContainsValue(null)) { return; }
foreach (int key in new List<int>(_blits.Keys))
{
if (_blits[key] == null) _blits.Remove(key);
}
}
}
}
}

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 00b3471f79f999345b21b7979abca356
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- sprayStampMaterial: {fileID: 2100000, guid: 44092c54cacca1046ac25e52c878a0c7, type: 2}
- waterBumpOverride: {fileID: 2800000, guid: 06aafc7fcb186454893618a0b137089b, type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,37 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: WaterSpray
m_Shader: {fileID: 4800000, guid: 14c4f10921fa2ed46b4a9be3c07abeee, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Stamp:
m_Texture: {fileID: 2800000, guid: c6766195a787bd94cbe3f230af954ee4, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _StampMultipler: 5
- _StampStrength: 3
- _Subtract: 0.002
- _UV: 1
m_Colors:
- _Subtract: {r: 0.039215688, g: 0.039215688, b: 0.039215688, a: 1}
m_BuildTextureStacks: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 44092c54cacca1046ac25e52c878a0c7
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
namespace Oculus.Interaction.Demo
{
public class WaterSprayNozzleTransformer : MonoBehaviour, ITransformer
{
[SerializeField]
private float _factor = 3f;
[SerializeField]
private float _snapAngle = 90;
[SerializeField]
[Range(0f, 1f)]
private float _snappiness = 0.8f;
[SerializeField]
private int _maxSteps = 1;
private float _relativeAngle = 0f;
private int _stepsCount = 0;
private IGrabbable _grabbable;
private Pose _previousGrabPose;
public void Initialize(IGrabbable grabbable)
{
_grabbable = grabbable;
}
public void BeginTransform()
{
_previousGrabPose = _grabbable.GrabPoints[0];
_relativeAngle = 0.0f;
_stepsCount = 0;
}
public void UpdateTransform()
{
Pose grabPoint = _grabbable.GrabPoints[0];
Transform targetTransform = _grabbable.Transform;
Vector3 localAxis = Vector3.forward;
Vector3 worldAxis = targetTransform.TransformDirection(localAxis);
Vector3 initialVector = Vector3.ProjectOnPlane(_previousGrabPose.right, worldAxis).normalized;
Vector3 targetVector = Vector3.ProjectOnPlane(grabPoint.right, worldAxis).normalized;
float angleDelta = Vector3.SignedAngle(initialVector, targetVector, worldAxis) * _factor;
_relativeAngle += angleDelta;
if (Mathf.Abs(_relativeAngle) > _snapAngle * (1 - _snappiness)
&& Mathf.Abs(_stepsCount + Mathf.Sign(_relativeAngle)) <= _maxSteps)
{
float currentAngle = targetTransform.localEulerAngles.z;
int turns = Mathf.FloorToInt((currentAngle + _snappiness * 0.5f) / _snapAngle);
float sign = Mathf.Sign(_relativeAngle);
float angle = sign > 0 ? _snapAngle * (turns + 1) : _snapAngle * turns;
Vector3 rot = targetTransform.localEulerAngles;
rot.z = angle;
targetTransform.localEulerAngles = rot;
_relativeAngle = 0;
_stepsCount += (int)sign;
}
else
{
targetTransform.Rotate(worldAxis, angleDelta, Space.World);
}
_previousGrabPose = grabPoint;
}
public void EndTransform() { }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1302feb954c92f43bb3d72f377721ee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eb0e4cf711387a24ba61894d49bb7cdd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
namespace Oculus.Interaction.Demo
{
/// <summary>
/// Supplies the 'main' directionl light properties to the BasicPBR shader
/// </summary>
public class BasicPBRGlobals : MonoBehaviour
{
[SerializeField]
private Light _mainlight;
private void Update()
{
UpateShaderGlobals();
}
private void UpateShaderGlobals()
{
Light light = _mainlight;
bool hasLight = light && light.isActiveAndEnabled;
Shader.SetGlobalVector("_BasicPBRLightDir", hasLight ? light.transform.forward : Vector3.down);
Shader.SetGlobalColor("_BasicPBRLightColor", hasLight ? light.color : Color.black);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 94217a4c67be3f143b2ac00d190c8bde
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8c201135db8d52149949bab567cd1fd6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,255 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
// PBR Shader adapted from Standard (Metallic) that works in built-in and URP pipelines
// Supports 1 directional light without specular
Shader "Unlit/BasicPBR"
{
Properties
{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Texture", 2D) = "white" {}
_Metallic("Metallic", Range(0,1)) = 0
_Gloss("Gloss", Range(0,1)) = 0
[NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
[NoScaleOffset] _WetMap("Wet Map", 2D) = "black" {}
[Enum(UV0,0,UV1,1)] _WetMapUV("Wet Map UV Set", Float) = 1
// droplets for non-porous horizontal surfaces
[HideInInspector] _WetBumpMap("Wet Bump Map", 2D) = "bump" {}
[Toggle(VERTEX_COLOR_LIGHTMAP)] _VertexColorLightmap("Vertex Color Lightmap", Float) = 0
_VertexColorLightmapScale("Vertex Color Lightmap Scale", Float) = 1
}
CGINCLUDE
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
fixed4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float3 tangentWS: TEXCOORD3;
float3 bitangentWS: TEXCOORD4;
float3 positionWS : TEXCOORD5;
fixed4 color : COLOR;
UNITY_FOG_COORDS(6)
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
// standard properties
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
fixed _Metallic;
fixed _Gloss;
sampler2D _WetMap;
half _WetMapUV;
sampler2D _WetBumpMap;
float _VertexColorLightmapScale;
// globals
float3 _BasicPBRLightDir;
fixed3 _BasicPBRLightColor;
v2f vert(appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_OUTPUT(v2f, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
o.uv1 = v.texcoord1;
o.positionWS = mul(unity_ObjectToWorld, v.vertex);
o.normalWS = normalize(UnityObjectToWorldNormal(v.normal));
o.tangentWS = normalize(mul(unity_ObjectToWorld, v.tangent).xyz);
o.bitangentWS = normalize(cross(o.normalWS, o.tangentWS.xyz));
o.color = v.color;
UNITY_TRANSFER_FOG(o, o.vertex);
return o;
}
// UnityStandardUtils.cginc#L46
half3 DiffuseAndSpecularFromMetallic(half3 albedo, half metallic, out half3 specColor, out half oneMinusReflectivity)
{
specColor = lerp(unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
half oneMinusDielectricSpec = unity_ColorSpaceDielectricSpec.a;
oneMinusReflectivity = oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
return albedo * oneMinusReflectivity;
}
// UnityImageBasedLighting.cginc#L522
half3 Unity_GlossyEnvironment(half3 reflectDir, half perceptualRoughness)
{
perceptualRoughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness);
half mip = perceptualRoughness * 6;
half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, reflectDir, mip);
return DecodeHDR(rgbm, unity_SpecCube1_HDR);
}
inline half3 Pow4(half3 x)
{
return x * x * x * x;
}
// UnityStandardBRDF.cginc#L92
inline half3 FresnelLerp(half3 F0, half3 F90, half cosA)
{
half t = Pow4(1 - cosA);
return lerp(F0, F90, t);
}
// UnityStandardBRDF.cginc#L299
half SurfaceReduction(float perceptualRoughness)
{
float roughness = perceptualRoughness * perceptualRoughness;
#ifdef UNITY_COLORSPACE_GAMMA
return 1.0 - 0.28 * roughness * perceptualRoughness;
#else
return 1.0 / (roughness * roughness + 1.0);
#endif
}
// UnityStandardBRDF.cginc#L338
float3 Specular(float roughness, float3 normal, float3 viewDir)
{
half3 halfDir = normalize(-_BasicPBRLightDir + viewDir);
float nh = saturate(dot(normal, halfDir));
float lh = saturate(dot(_BasicPBRLightDir, halfDir));
float a = roughness * roughness;
float a2 = a * a;
float d = nh * nh * (a2 - 1.f) + 1.00001f;
#ifdef UNITY_COLORSPACE_GAMMA
float specularTerm = a / (max(0.32f, lh) * (1.5f + a) * d);
#else
float specularTerm = a2 / (max(0.1f, lh * lh) * (a + 0.5f) * (d * d) * 4);
#endif
#if defined (SHADER_API_MOBILE)
specularTerm = specularTerm - 1e-4f;
#endif
return specularTerm * 0.3f;
}
// https://seblagarde.wordpress.com/2013/04/14/water-drop-3b-physically-based-wet-surfaces/
void AddWater(float2 uv, float metalness, inout half3 diffuse, inout float smoothness, inout fixed4 bumpMap, float2 wsPos, float3 normalWS)
{
fixed wetMap = tex2D(_WetMap, uv).r;
float porosity = saturate((1 - smoothness) - 0.2);//saturate(((1-Gloss) - 0.5)) / 0.4 );
float factor = lerp(1, 0.2, (1 - metalness) * porosity);
float collectWater = max(0, normalWS.y);
diffuse *= lerp(1.0, factor, wetMap);
smoothness = lerp(smoothness, 0.95, saturate(wetMap * wetMap));// lerp(1, factor, 0.5 * wetMap));
bumpMap = lerp(bumpMap, tex2D(_WetBumpMap, wsPos * 20), wetMap * collectWater);
}
fixed4 frag(v2f i) : SV_Target
{
// BRDF texture inputs
fixed4 mainTex = tex2D(_MainTex, i.uv0);
float4 bumpMap = tex2D(_BumpMap, i.uv0);
// BEDF values
fixed3 albedo = mainTex.rgb * _Color.rgb;
float metalness = _Metallic;
float smoothness = _Gloss;
float oneMinusReflectivity;
float3 specColor;
float3 diffColor = DiffuseAndSpecularFromMetallic(albedo.rgb, metalness, /*out*/ specColor, /*out*/ oneMinusReflectivity);
AddWater((_WetMapUV == 0) ? i.uv0 : i.uv1, metalness, /*inout*/ diffColor, /*inout*/ smoothness, /*inout*/ bumpMap, i.positionWS.xz, i.normalWS);
float3x3 tangentMatrix = transpose(float3x3(i.tangentWS, i.bitangentWS, i.normalWS));
float3 normal = normalize(mul(tangentMatrix, UnpackNormal(bumpMap)));
float3 ambient =
#if VERTEX_COLOR_LIGHTMAP
i.color.rgb * _VertexColorLightmapScale;
#else
ShadeSH9(float4(normal, 1));
#endif
half nl = saturate(dot(normal, -_BasicPBRLightDir));
half3 diffuse = diffColor * (ambient + _BasicPBRLightColor * nl);
float perceptualRoughness = 1 - smoothness;
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.positionWS);
half nv = abs(dot(normal, viewDir));
float3 reflectDir = -reflect(viewDir, normal);
float3 specularGI = Unity_GlossyEnvironment(reflectDir, perceptualRoughness);
half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity));
half3 specular = SurfaceReduction(perceptualRoughness) * specularGI * FresnelLerp(specColor, grazingTerm, nv); +
+ Specular(perceptualRoughness, normal, viewDir) * specColor * nl * _BasicPBRLightColor;
// non BRDF texture inputs
half3 color = (diffuse + specular);
UNITY_APPLY_FOG(i.fogCoord, color);
return fixed4(color, 1);
}
ENDCG
SubShader
{
Tags{ "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Pass
{
Tags{ "LightMode" = "UniversalForward" }
CGPROGRAM
#pragma shader_feature VERTEX_COLOR_LIGHTMAP
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
ENDCG
}
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma shader_feature VERTEX_COLOR_LIGHTMAP
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
ENDCG
}
}
}

View File

@ -0,0 +1,17 @@
fileFormatVersion: 2
guid: f98fc22324f0f5248bc2a4b595aa681d
ShaderImporter:
externalObjects: {}
defaultTextures:
- _MainTex: {instanceID: 0}
- _MetallicGlossMap: {instanceID: 0}
- _BumpMap: {instanceID: 0}
- _OcclusionMap: {instanceID: 0}
- _EmissionMap: {instanceID: 0}
- _WetMap: {instanceID: 0}
- _WetBumpMap: {fileID: 2800000, guid: 06aafc7fcb186454893618a0b137089b, type: 3}
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant: