Skip to content

Commit

Permalink
Merge branch 'main' into grid-mesh
Browse files Browse the repository at this point in the history
  • Loading branch information
kpal81xd authored Dec 9, 2024
2 parents fbde0c2 + fd10688 commit 4858b43
Show file tree
Hide file tree
Showing 83 changed files with 2,153 additions and 1,480 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ assetListLoader.load(() => {
const cylinderMesh = pc.Mesh.fromGeometry(app.graphicsDevice, new pc.CylinderGeometry({ capSegments: 200 }));
const cylinder = new pc.Entity();
cylinder.addComponent('render', {
material: material,
meshInstances: [new pc.MeshInstance(cylinderMesh, material)],
castShadows: true
});
Expand Down
9 changes: 6 additions & 3 deletions examples/src/examples/graphics/integer-textures.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,15 @@ const createPixelColorBuffer = (i) => {
name: `PixelBuffer_${i}`,
width: TEXTURE_WIDTH,
height: TEXTURE_HEIGHT,
mipmaps: false,
addressU: pc.ADDRESS_CLAMP_TO_EDGE,
addressV: pc.ADDRESS_CLAMP_TO_EDGE,

// Note that we are using an unsigned integer format here.
// This can be helpful for storing bitfields in each pixel.
// In this example, we are storing 3 different properties
// in a single Uint8 value.
format: pc.PIXELFORMAT_R8U,
addressU: pc.ADDRESS_CLAMP_TO_EDGE,
addressV: pc.ADDRESS_CLAMP_TO_EDGE
format: pc.PIXELFORMAT_R8U
});
};
const createPixelRenderTarget = (i, colorBuffer) => {
Expand All @@ -114,6 +116,7 @@ const outputTexture = new pc.Texture(device, {
name: 'OutputTexture',
width: TEXTURE_WIDTH,
height: TEXTURE_HEIGHT,
mipmaps: false,
format: pc.PIXELFORMAT_RGBA8,
minFilter: pc.FILTER_LINEAR_MIPMAP_LINEAR,
magFilter: pc.FILTER_LINEAR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pc.WasmModule.setConfig('DracoDecoderModule', {
const assets = {
laboratory: new pc.Asset('statue', 'container', { url: `${rootPath}/static/assets/models/laboratory.glb` }),
orbit: new pc.Asset('orbit', 'script', { url: `${rootPath}/static/scripts/camera/orbit-camera.js` }),
ssao: new pc.Asset('ssao', 'script', { url: `${rootPath}/static/scripts/posteffects/posteffect-ssao.js` }),
helipad: new pc.Asset(
'helipad-env-atlas',
'texture',
Expand Down
2 changes: 0 additions & 2 deletions examples/src/examples/graphics/render-to-texture.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@ assetListLoader.load(() => {
height: 256,
format: pc.PIXELFORMAT_SRGBA8,
mipmaps: true,
minFilter: pc.FILTER_LINEAR,
magFilter: pc.FILTER_LINEAR,
addressU: pc.ADDRESS_CLAMP_TO_EDGE,
addressV: pc.ADDRESS_CLAMP_TO_EDGE
});
Expand Down
1 change: 0 additions & 1 deletion examples/src/examples/loaders/gsplat-many.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ assetListLoader.load(() => {

// instantiate guitar with a custom shader
const guitar = assets.guitar.resource.instantiate({
fragment: files['shader.frag'],
vertex: files['shader.vert']
});
guitar.name = 'guitar';
Expand Down
34 changes: 0 additions & 34 deletions examples/src/examples/loaders/gsplat-many.shader.frag

This file was deleted.

105 changes: 54 additions & 51 deletions examples/src/examples/loaders/gsplat-many.shader.vert
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
}
}
2 changes: 1 addition & 1 deletion package.json
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",
Expand Down
20 changes: 14 additions & 6 deletions scripts/esm/camera-controls.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -848,20 +848,24 @@ class CameraControls extends Script {
tmpV1.sub2(start, point);
const elev = Math.atan2(tmpV1.y, Math.sqrt(tmpV1.x * tmpV1.x + tmpV1.z * tmpV1.z)) * math.RAD_TO_DEG;
const azim = Math.atan2(tmpV1.x, tmpV1.z) * math.RAD_TO_DEG;
this._dir.set(-elev, -azim);
this._dir.set(this._clampPitch(-elev), azim);

this._origin.copy(point);

this._cameraTransform.setTranslate(0, 0, 0);
this._baseTransform.setTRS(this._origin, Quat.IDENTITY, Vec3.ONE);

this._zoomDist = tmpV1.length();
const pos = this._camera.entity.getPosition();
const rot = this._camera.entity.getRotation();
this._baseTransform.setTRS(pos, rot, Vec3.ONE);

this._zoomDist = this._clampZoom(tmpV1.length());

if (!smooth) {
this._angles.set(this._dir.x, this._dir.y, 0);
this._position.copy(point);
this._cameraDist = this._zoomDist;
this._smoothZoom(-1);
this._smoothTransform(-1);
}

this._updateTransform();
}

/**
Expand Down Expand Up @@ -947,6 +951,10 @@ class CameraControls extends Script {
* @param {number} dt - The delta time.
*/
update(dt) {
if (this.app.xr?.active) {
return;
}

if (!this._camera) {
return;
}
Expand Down
101 changes: 101 additions & 0 deletions scripts/esm/xr-controllers.mjs
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());
}
}
}
}
}
Loading

0 comments on commit 4858b43

Please sign in to comment.