-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
83 changed files
with
2,153 additions
and
1,480 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +1,82 @@ | ||
#include "gsplatCommonVS" | ||
|
||
varying mediump vec2 gaussianUV; | ||
varying mediump vec4 gaussianColor; | ||
|
||
#ifndef DITHER_NONE | ||
varying float id; | ||
#endif | ||
|
||
mediump vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0); | ||
|
||
uniform float uTime; | ||
varying float height; | ||
|
||
void animate(inout vec3 center) { | ||
vec3 animatePosition(vec3 center) { | ||
// modify center | ||
float heightIntensity = center.y * 0.2; | ||
center.x += sin(uTime * 5.0 + center.y) * 0.3 * heightIntensity; | ||
|
||
// output y-coordinate | ||
height = center.y; | ||
return center; | ||
} | ||
|
||
uniform vec3 view_position; | ||
|
||
uniform sampler2D splatColor; | ||
|
||
varying mediump vec2 texCoord; | ||
varying mediump vec4 color; | ||
vec4 animateColor(float height, vec4 clr) { | ||
float sineValue = abs(sin(uTime * 5.0 + height)); | ||
|
||
#ifdef CUTOUT | ||
// in cutout mode, remove pixels along the wave | ||
if (sineValue < 0.5) { | ||
clr.a = 0.0; | ||
} | ||
#else | ||
// in non-cutout mode, add a golden tint to the wave | ||
vec3 gold = vec3(1.0, 0.85, 0.0); | ||
float blend = smoothstep(0.9, 1.0, sineValue); | ||
clr.xyz = mix(clr.xyz, gold, blend); | ||
#endif | ||
|
||
mediump vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0); | ||
return clr; | ||
} | ||
|
||
void main(void) | ||
{ | ||
// calculate splat uv | ||
if (!calcSplatUV()) { | ||
void main(void) { | ||
// read gaussian center | ||
SplatSource source; | ||
if (!initSource(source)) { | ||
gl_Position = discardVec; | ||
return; | ||
} | ||
|
||
// get center | ||
vec3 center = getCenter(); | ||
|
||
animate(center); | ||
vec3 centerPos = animatePosition(readCenter(source)); | ||
|
||
// handle transforms | ||
mat4 model_view = matrix_view * matrix_model; | ||
vec4 splat_cam = model_view * vec4(center, 1.0); | ||
vec4 splat_proj = matrix_projection * splat_cam; | ||
SplatCenter center; | ||
initCenter(source, centerPos, center); | ||
|
||
// cull behind camera | ||
if (splat_proj.z < -splat_proj.w) { | ||
// project center to screen space | ||
SplatCorner corner; | ||
if (!initCorner(source, center, corner)) { | ||
gl_Position = discardVec; | ||
return; | ||
} | ||
|
||
// get covariance | ||
vec3 covA, covB; | ||
getCovariance(covA, covB); | ||
// read color | ||
vec4 clr = readColor(source); | ||
|
||
vec4 v1v2 = calcV1V2(splat_cam.xyz, covA, covB, transpose(mat3(model_view))); | ||
|
||
// get color | ||
color = texelFetch(splatColor, splatUV, 0); | ||
|
||
// calculate scale based on alpha | ||
float scale = min(1.0, sqrt(-log(1.0 / 255.0 / color.a)) / 2.0); | ||
|
||
v1v2 *= scale; | ||
|
||
// early out tiny splats | ||
if (dot(v1v2.xy, v1v2.xy) < 4.0 && dot(v1v2.zw, v1v2.zw) < 4.0) { | ||
gl_Position = discardVec; | ||
return; | ||
} | ||
// evaluate spherical harmonics | ||
#if SH_BANDS > 0 | ||
vec3 dir = normalize(center.view * mat3(center.modelView)); | ||
clr.xyz += evalSH(state, dir); | ||
#endif | ||
|
||
gl_Position = splat_proj + vec4((vertex_position.x * v1v2.xy + vertex_position.y * v1v2.zw) / viewport * splat_proj.w, 0, 0); | ||
clr = animateColor(centerPos.y, clr); | ||
|
||
texCoord = vertex_position.xy * scale / 2.0; | ||
clipCorner(corner, clr.w); | ||
|
||
#ifdef USE_SH1 | ||
vec4 worldCenter = matrix_model * vec4(center, 1.0); | ||
vec3 viewDir = normalize((worldCenter.xyz / worldCenter.w - view_position) * mat3(matrix_model)); | ||
color.xyz = max(color.xyz + evalSH(viewDir), 0.0); | ||
#endif | ||
// write output | ||
gl_Position = center.proj + vec4(corner.offset, 0.0, 0.0); | ||
gaussianUV = corner.uv; | ||
gaussianColor = vec4(prepareOutputFromGamma(max(clr.xyz, 0.0)), clr.w); | ||
|
||
#ifndef DITHER_NONE | ||
id = float(splatId); | ||
id = float(state.id); | ||
#endif | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "playcanvas", | ||
"version": "2.3.0-dev", | ||
"version": "2.4.0-dev", | ||
"author": "PlayCanvas <[email protected]>", | ||
"homepage": "https://playcanvas.com", | ||
"description": "PlayCanvas WebGL game engine", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* eslint-disable-next-line import/no-unresolved */ | ||
import { Script } from 'playcanvas'; | ||
|
||
export default class XrControllers extends Script { | ||
/** | ||
* The base URL for fetching the WebXR input profiles. | ||
* | ||
* @attribute | ||
* @type {string} | ||
*/ | ||
basePath = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets/dist/profiles'; | ||
|
||
controllers = new Map(); | ||
|
||
initialize() { | ||
this.app.xr.input.on('add', async (inputSource) => { | ||
if (!inputSource.profiles?.length) { | ||
console.warn('No profiles available for input source'); | ||
return; | ||
} | ||
|
||
// Process all profiles concurrently | ||
const profilePromises = inputSource.profiles.map(async (profileId) => { | ||
const profileUrl = `${this.basePath}/${profileId}/profile.json`; | ||
|
||
try { | ||
const response = await fetch(profileUrl); | ||
if (!response.ok) { | ||
return null; | ||
} | ||
|
||
const profile = await response.json(); | ||
const layoutPath = profile.layouts[inputSource.handedness]?.assetPath || ''; | ||
const assetPath = `${this.basePath}/${profile.profileId}/${inputSource.handedness}${layoutPath.replace(/^\/?(left|right)/, '')}`; | ||
|
||
// Load the model | ||
const asset = await new Promise((resolve, reject) => { | ||
this.app.assets.loadFromUrl(assetPath, 'container', (err, asset) => { | ||
if (err) reject(err); | ||
else resolve(asset); | ||
}); | ||
}); | ||
|
||
return { profileId, asset }; | ||
} catch (error) { | ||
console.warn(`Failed to process profile ${profileId}`); | ||
return null; | ||
} | ||
}); | ||
|
||
// Wait for all profile attempts to complete | ||
const results = await Promise.all(profilePromises); | ||
const successfulResult = results.find(result => result !== null); | ||
|
||
if (successfulResult) { | ||
const { asset } = successfulResult; | ||
const container = asset.resource; | ||
const entity = container.instantiateRenderEntity(); | ||
this.app.root.addChild(entity); | ||
|
||
const jointMap = new Map(); | ||
if (inputSource.hand) { | ||
for (const joint of inputSource.hand.joints) { | ||
const jointEntity = entity.findByName(joint.id); | ||
if (jointEntity) { | ||
jointMap.set(joint, jointEntity); | ||
} | ||
} | ||
} | ||
|
||
this.controllers.set(inputSource, { entity, jointMap }); | ||
} else { | ||
console.warn('No compatible profiles found'); | ||
} | ||
}); | ||
|
||
this.app.xr.input.on('remove', (inputSource) => { | ||
const controller = this.controllers.get(inputSource); | ||
if (controller) { | ||
controller.entity.destroy(); | ||
this.controllers.delete(inputSource); | ||
} | ||
}); | ||
} | ||
|
||
update(dt) { | ||
if (this.app.xr.active) { | ||
for (const [inputSource, { entity, jointMap }] of this.controllers) { | ||
if (inputSource.hand) { | ||
for (const [joint, jointEntity] of jointMap) { | ||
jointEntity.setPosition(joint.getPosition()); | ||
jointEntity.setRotation(joint.getRotation()); | ||
} | ||
} else { | ||
entity.setPosition(inputSource.getPosition()); | ||
entity.setRotation(inputSource.getRotation()); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.