Skip to content

Commit

Permalink
grid sphere shape
Browse files Browse the repository at this point in the history
  • Loading branch information
slimbuck committed Aug 5, 2024
1 parent 3a1dae4 commit fd23da6
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 9 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "supersplat",
"version": "1.0.0",
"version": "1.0.0-alpha.0",
"author": "PlayCanvas<[email protected]>",
"homepage": "https://playcanvas.com/supersplat/editor",
"description": "3D Gaussian Splat Editor",
Expand Down
5 changes: 3 additions & 2 deletions src/infinite-grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
Mat4,
QuadRender,
Shader,
createShaderFromCode
createShaderFromCode,
FUNC_LESSEQUAL
} from 'playcanvas';
import { Element, ElementType } from './element';
import { Serializer } from './serializer';
Expand Down Expand Up @@ -161,7 +162,7 @@ class InfiniteGrid extends Element {
shader: Shader;
quadRender: QuadRender;
blendState = new BlendState(false);
depthState = new DepthState(FUNC_ALWAYS, true);
depthState = new DepthState(FUNC_LESSEQUAL, true);

visible = true;

Expand Down
147 changes: 143 additions & 4 deletions src/sphere-shape.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,157 @@
import { BoundingBox, Color, Entity, Vec3 } from 'playcanvas';
import {
createShaderFromCode,
CULLFACE_NONE,
BoundingBox,
Entity,
Material,
Vec3
} from 'playcanvas';
import { Element, ElementType } from './element';
import { Serializer } from './serializer';

const vsCode = /* glsl */ `
attribute vec3 vertex_position;
uniform mat4 matrix_model;
uniform mat4 matrix_viewProjection;
varying vec3 fragWorld;
void main() {
vec4 world = matrix_model * vec4(vertex_position, 1.0);
gl_Position = matrix_viewProjection * world;
fragWorld = world.xyz;
}
`;

const fsCode = /* glsl */ `
bool intersectSphere(out float t0, out float t1, vec3 pos, vec3 dir, vec4 sphere) {
vec3 L = sphere.xyz - pos;
float tca = dot(L, dir);
float d2 = sphere.w * sphere.w - (dot(L, L) - tca * tca);
if (d2 < 0.0) {
return false;
}
float thc = sqrt(d2);
t0 = tca - thc;
t1 = tca + thc;
if (t1 < 0.0) {
return false;
}
return true;
}
float calcDepth(in vec3 pos, in mat4 viewProjection) {
vec4 v = viewProjection * vec4(pos, 1.0);
return (v.z / v.w) * 0.5 + 0.5;
}
float noise(vec2 fragCoord, sampler2D noiseTex) {
vec2 uv = fract(fragCoord / 32.0);
return texture2DLodEXT(noiseTex, uv, 0.0).y;
}
vec2 calcAzimuthElev(in vec3 dir) {
float azimuth = atan(dir.z, dir.x);
float elev = asin(dir.y);
return vec2(azimuth, elev) * 180.0 / 3.14159;
}
bool strips(vec3 lp) {
vec2 ae = calcAzimuthElev(normalize(lp));
float spacing = 10.0;
float size = 0.25 / spacing;
return fract(ae.x / spacing) > size &&
fract(ae.y / spacing) > size;
}
uniform sampler2D blueNoiseTex32;
uniform vec3 view_position;
uniform mat4 matrix_viewProjection;
uniform vec4 sphere;
varying vec3 fragWorld;
void behind(vec3 ray, float t) {
vec3 wp = view_position + ray * t;
if (strips(wp - sphere.xyz) || noise(gl_FragCoord.yx, blueNoiseTex32) < 0.125) {
discard;
}
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
gl_FragDepth = calcDepth(wp, matrix_viewProjection);
}
void front(vec3 ray, float t0, float t1) {
if (t0 < 0.0) {
behind(ray, t1);
} else {
vec3 wp = view_position + ray * t0;
if (strips(wp - sphere.xyz) || noise(gl_FragCoord.xy, blueNoiseTex32) < 0.6) {
behind(ray, t1);
} else {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
gl_FragDepth = calcDepth(wp, matrix_viewProjection);
}
}
}
void main() {
vec3 ray = normalize(fragWorld - view_position);
float t0, t1;
if (!intersectSphere(t0, t1, view_position, ray, sphere)) {
discard;
}
front(ray, t0, t1);
}
`;

const v = new Vec3();
const bound = new BoundingBox();

class SphereShape extends Element {
pivot: Entity;
_radius = 1;
pivot: Entity;
material: Material;

constructor() {
super(ElementType.debug);

this.pivot = new Entity('spherePivot');
this.pivot.addComponent('render', {
type: 'box'
});
const r = this._radius * 2;
this.pivot.setLocalScale(r, r, r);
}

add() {
const device = this.scene.app.graphicsDevice;

const shader = createShaderFromCode(
device,
vsCode,
fsCode,
'sphere-shape'
);

const material = new Material();
material.shader = shader;
material.cull = CULLFACE_NONE;
material.update();

this.pivot.render.meshInstances[0].material = material;

this.material = material;

this.scene.contentRoot.addChild(this.pivot);

this.updateBound();
}

Expand All @@ -35,8 +170,8 @@ class SphereShape extends Element {
}

onPreRender() {
this.pivot.getWorldTransform().getTranslation(v)
this.scene.app.drawWireSphere(v, this.radius, Color.RED, 40);
this.pivot.getWorldTransform().getTranslation(v);
this.material.setParameter('sphere', [v.x, v.y, v.z, this.radius]);
}

moved() {
Expand All @@ -55,6 +190,10 @@ class SphereShape extends Element {

set radius(radius: number) {
this._radius = radius;

const r = this._radius * 2;
this.pivot.setLocalScale(r, r, r);

this.updateBound();
}

Expand Down

0 comments on commit fd23da6

Please sign in to comment.