Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/systems/moving.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { TransformData } from "@core/components/transform";
import type { Sim } from "../sim";
import type { RequireComponent } from "../tsHelpers";
import { System } from "./system";
import { transport3D } from "./transport3d";

const baseMaxSpeed = 8;

Expand Down Expand Up @@ -77,6 +78,7 @@ export class MovingSystem extends System {
this.move(entity, delta);
}
}
transport3D.publish({ type: "movingSystemFinished" });
}
}

Expand Down
6 changes: 5 additions & 1 deletion core/systems/transport3d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@ export type DeployFacilityEvent = {
type: "deployFacility";
entity: RequireComponent<"position">;
};
export type MovingSystemFinishedEvent = {
type: "movingSystemFinished";
};

export type Event3D =
| ShootEvent
| ExplodeEvent
| StartMiningEvent
| StopMiningEvent
| DeployFacilityEvent;
| DeployFacilityEvent
| MovingSystemFinishedEvent;

export const transport3D = new PubSub<Event3D>();
4 changes: 4 additions & 0 deletions core/utils/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,7 @@ export function isVec2(v: object): v is { value: number[] } {
export function lerp(a: number, b: number, t: number): number {
return a + (b - a) * t;
}

export function triangle(a: number): number {
return 1 - Math.abs(((a / 2) % 1) * 2 - 1);
}
121 changes: 73 additions & 48 deletions ogl-engine/RibbonEmitter.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type { OGLRenderingContext } from "ogl";
import { Geometry, Vec3 } from "ogl";
import { triangle } from "@core/utils/misc";
import { BaseMesh } from "./engine/BaseMesh";
import { EngineTrailMaterial } from "./materials/engineTrail/engineTrail";
import type { OnBeforeRenderTask } from "./engine/task";

const tempVec3 = new Vec3();
const tempVec32 = new Vec3();
const tempVec33 = new Vec3();
const tempVec34 = new Vec3();
const tempDir = new Vec3();
const tempNormal = new Vec3();
const tempNormalForward = new Vec3();
const tempNormalBackward = new Vec3();
const up = new Vec3(0, 1, 0);

export class RibbonGeometry extends Geometry {
readonly maxSegments: number;
Expand All @@ -18,23 +22,22 @@ export class RibbonGeometry extends Geometry {
segments?: Float32Array,
width = 0.3
) {
const position = new Float32Array((maxSegments - 1) * 4 * 3);
const uv = new Float32Array((maxSegments - 1) * 4 * 2);
const index = new Uint16Array((maxSegments - 1) * 6);
const position = new Float32Array(maxSegments * 2 * 3 * 2);
const uv = new Float32Array(maxSegments * 2 * 2 * 2);
const index = new Uint16Array(position.length / 3);

if (segments) {
RibbonGeometry.build(segments, position, new Vec3(0, 1, 0), width);
RibbonGeometry.build(segments, position, width);
}

for (let i = 0; i < maxSegments - 1; i++) {
index.set(
[i * 4, i * 4 + 2, i * 4 + 1, i * 4 + 2, i * 4 + 3, i * 4 + 1],
i * 6
);
for (let i = 0; i < index.length; i++) {
index[i] = i;
}

const uvOffset = i * 2 * 4;
const xStart = i / (maxSegments - 1);
const xEnd = (i + 1) / (maxSegments - 1);
for (let i = 0; i < maxSegments * 2; i++) {
const uvOffset = i * 2 * 2;
const xStart = triangle(i / maxSegments);
const xEnd = triangle((i + 1) / maxSegments);

uv[uvOffset] = xStart;
uv[uvOffset + 1] = 0;
Expand Down Expand Up @@ -68,30 +71,64 @@ export class RibbonGeometry extends Geometry {
static build(
segments: Float32Array,
position: Float32Array,
cameraDirection: Vec3,
width: number
width: number,
lengthOverride?: number
) {
const length = segments.length / 4;
for (let i = 0; i < length - 1; i++) {
const segment = segments.subarray(i * 4, i * 4 + 4);
const nextSegment = segments.subarray((i + 1) * 4, (i + 1) * 4 + 4);

const dir = tempDir
.fromArray(nextSegment)
.sub(tempVec32.set(segment[0], segment[1], segment[2]))
for (let i = 0; i < (lengthOverride ?? segments.length / 4); i++) {
const segment = tempVec32.fromArray(
segments.subarray(i * 4, (i + 1) * 4)
);
const prevSegment = tempVec33.fromArray(
segments.subarray((i - 1) * 4, i * 4)
);
const nextSegment = tempVec34.fromArray(
segments.subarray((i + 1) * 4, (i + 2) * 4)
);

const dir = tempDir.copy(nextSegment).sub(segment).normalize();
const normalForward = tempNormalForward.cross(dir, up).normalize();
const dirBackward = tempDir.copy(segment).sub(prevSegment).normalize();
const normalBackward = tempNormalBackward
.cross(dirBackward, up)
.normalize();
const normal = tempNormal
.cross(dir, cameraDirection)
.normalize()
.multiply(width);

const vertOffset = i * 3 * 4;
position.set(tempVec3.set(tempVec32).add(normal), vertOffset);
position.set(tempVec3.set(tempVec32).sub(normal), vertOffset + 3);
position.set(tempVec3.fromArray(nextSegment).add(normal), vertOffset + 6);
position.set(tempVec3.fromArray(nextSegment).sub(normal), vertOffset + 9);

let normal = normalForward;
if (i === segments.length / 4 - 1) {
normal = normalBackward;
} else if (i > 0) {
normal = normalForward.add(normalBackward).scale(0.5).normalize();
}
normal.multiply(width);

const vertOffset = i * 3 * 2;
position.set(tempVec3.copy(segment).add(normal), vertOffset);
position.set(tempVec3.copy(segment).sub(normal), vertOffset + 3);

normal.copy(up).scale(width);

position.set(
tempVec3.copy(segment).add(normal),
position.length - 3 - vertOffset
);
position.set(
tempVec3.copy(segment).sub(normal),
position.length - 3 - (vertOffset + 3)
);
}
}

static addSegment(
segments: Float32Array,
position: Float32Array,
width: number
) {
position.set(position.subarray(0, position.length / 2 - 3 * 4), 3 * 4);
position.set(
position.subarray(position.length / 2 + 3 * 4),
position.length / 2
);
RibbonGeometry.build(segments, position, width, 3);
}
}

export class RibbonEmitter extends BaseMesh<EngineTrailMaterial> {
Expand All @@ -101,7 +138,6 @@ export class RibbonEmitter extends BaseMesh<EngineTrailMaterial> {
width = 0.3;
maxSegments = 25;
initialised = false;
task: OnBeforeRenderTask;

constructor(
trackedEntity: BaseMesh,
Expand All @@ -115,17 +151,14 @@ export class RibbonEmitter extends BaseMesh<EngineTrailMaterial> {
geometry: new RibbonGeometry(trackedEntity.engine.gl, maxSegments),
material: new EngineTrailMaterial(trackedEntity.engine, "#ff00ff"),
calculateTangents: false,
mode: trackedEntity.engine.gl.TRIANGLE_STRIP,
});
this.maxSegments = maxSegments;
this.width = width;
this.trackedEntity = trackedEntity;
this.offset = offset || new Vec3();
this.engine = trackedEntity.engine;
this.segments = new Float32Array(maxSegments * 4);

this.task = this.engine.addOnBeforeRenderTask(() => {
this.update(this.engine.delta);
});
}

update(delta: number) {
Expand Down Expand Up @@ -157,20 +190,12 @@ export class RibbonEmitter extends BaseMesh<EngineTrailMaterial> {
updateGeometry() {
if (this.segments.length < 2) return;

RibbonGeometry.build(
RibbonGeometry.addSegment(
this.segments,
this.geometry.attributes.position.data! as Float32Array,
tempVec3
.copy(this.trackedEntity.position)
.sub(this.engine.camera.position)
.normalize(),
this.width * this.trackedEntity.scale.x
);

this.geometry.attributes.position.needsUpdate = true;
}

destroy() {
this.task.cancel();
}
}
7 changes: 7 additions & 0 deletions ogl-engine/engine/Scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ export class TacticalMapScene extends Scene {
max: 1,
}
);
this.pane
.addButton({
title: "Toggle UI",
})
.on("click", () =>
this.engine.togglePostProcessingPass("composite", "ui")
);
}

destroy() {
Expand Down
21 changes: 12 additions & 9 deletions ogl-engine/materials/color/color.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ProgramOptions } from "ogl";
import { Vec3, Program } from "ogl";
import type { Engine3D } from "@ogl-engine/engine/engine3d";
import type { Engine2D } from "@ogl-engine/engine/engine2d";
Expand All @@ -22,18 +23,20 @@ export class ColorMaterial extends Material {
opts: {
color?: string;
shaded?: boolean;
} = {}
layer?: string;
} & Partial<Omit<ProgramOptions, "vertex" | "fragment" | "uniforms">> = {}
) {
super(engine);

this.createProgram(
vertex,
fragment,
{},
{
cullFace: false,
}
);
const defines: Record<string, string> = {};
if (opts.layer) {
defines.LAYER = opts.layer;
}

this.createProgram(vertex, fragment, defines, {
cullFace: false,
...opts,
});

this.uniforms.uColor = { value: new Vec3() };
this.uniforms.fEmissive = { value: 0 };
Expand Down
14 changes: 10 additions & 4 deletions ogl-engine/materials/color/shader.frag.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#version 300 es
precision highp float;

#pragma defines
#ifndef LAYER
#define LAYER 0
#endif

#pragma glslify: blinnPhongSpec = require(glsl-specular-blinn-phong)
#pragma glslify: Light = require("./ogl-engine/shader/light");

Expand Down Expand Up @@ -46,12 +51,13 @@ void main() {
}
}

fragData[0].rgb = (diffuse + ambient + specular) * uColor;
fragData[LAYER].rgb = (diffuse + ambient + specular) * uColor;
} else {
fragData[0] = vec4(uColor, 1.f);
fragData[LAYER] = vec4(uColor, 1.f);
}

fragData[0].a = 1.0f;
fragData[1] = vec4(fragData[0].xyz, fEmissive);
fragData[LAYER].a = 1.0f;
fragData[1] = vec4(fragData[LAYER].xyz, fEmissive);

gl_FragDepth = log2(vFragDepth) / uCameraScale;
}
8 changes: 4 additions & 4 deletions ogl-engine/materials/engineTrail/shader.frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ uniform vec3 uColor;
uniform float uCameraScale;

#define emissive 0.9f
#define K 0.02
#define K 0.01f

void main() {
float alphaX = 1.f - vUv.x;
float alphaX = pow(1.f - vUv.x, 3.f);
float alphaFactorY = (vUv.y - 0.5f) * 2.0f;
float alphaY = K / (K + alphaFactorY * alphaFactorY) - K;
float alpha = alphaX * alphaY;
float alpha = clamp(alphaX * alphaY - 0.005f, 0.f, 0.85f);

fragData[0] = vec4(mix(uColor, vec3(1.f), pow(alphaY, 2.f) - 0.4f), alpha);
fragData[0] = vec4(mix(uColor, vec3(1.f), pow(alphaY, 2.f) - 0.1f), alpha);
fragData[1] = vec4(fragData[0].rgb, emissive * alpha);
gl_FragDepth = log2(vFragDepth) / uCameraScale;
}
1 change: 1 addition & 0 deletions ogl-engine/materials/engineTrail/shader.vert.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ uniform mat4 projectionMatrix;

void main() {
vUv = uv;

gl_Position = projectionMatrix * viewMatrix * vec4(position, 1.0f);
vFragDepth = 1.0f + gl_Position.w;
}
4 changes: 3 additions & 1 deletion ogl-engine/materials/material.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { entries, join, map, pipe } from "@fxts/core";
import type { Engine3D } from "@ogl-engine/engine/engine3d";
import type { Light } from "@ogl-engine/engine/Light";
import Color from "color";
import type { ProgramOptions, Mesh, Vec3, Vec4, Mat4 } from "ogl";
import type { ProgramOptions, Mesh, Vec3, Vec4, Mat4, Vec2 } from "ogl";
import { Texture, Program } from "ogl";
import type { BindingParams, FolderApi } from "tweakpane";
import { getPane } from "@ui/context/Pane";
Expand All @@ -28,6 +28,7 @@ export abstract class Material {
uTime: number;
tEnvMap: Texture;
uCameraScale: number;
uResolution: Vec2;
invProjectionMatrix: Mat4;
invViewMatrix: Mat4;
invViewProjectionMatrix: Mat4;
Expand All @@ -43,6 +44,7 @@ export abstract class Material {
uTime: engine.uniforms.uTime,
tEnvMap: engine.uniforms.env.tEnvMap,
uCameraScale: { value: Math.log2(engine.camera.far) },
uResolution: engine.uniforms.resolution.base,
invProjectionMatrix: { value: engine.camera.invProjectionMatrix },
invViewMatrix: { value: engine.camera.invViewMatrix },
invViewProjectionMatrix: { value: engine.camera.invViewProjectionMatrix },
Expand Down
Loading
Loading