mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-05 15:28:29 +08:00
Improved rendering of entities that use additive blending in NPCs/Objects panels.
This commit is contained in:
parent
eb5b539b6d
commit
78c18eb1e9
@ -151,7 +151,6 @@ Features that are in ***bold italics*** are planned but not yet implemented.
|
|||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
|
|
||||||
- [NPC/Object Manipulation](#npcobject-manipulation): Entities in NPCs/Objects panels with additive blending aren't rendered correctly.
|
|
||||||
- [Load Quest](#load-quest): Can't parse quest 125 White Day
|
- [Load Quest](#load-quest): Can't parse quest 125 White Day
|
||||||
- [Script Assembly Editor](#script-assembly-editor): Go to definition doesn't work in RT (#231)
|
- [Script Assembly Editor](#script-assembly-editor): Go to definition doesn't work in RT (#231)
|
||||||
- When a modal dialog is open, global keybindings should be disabled
|
- When a modal dialog is open, global keybindings should be disabled
|
||||||
|
@ -2,10 +2,10 @@ import { initialize_application } from "./index";
|
|||||||
import { LogHandler, LogManager } from "../core/Logger";
|
import { LogHandler, LogManager } from "../core/Logger";
|
||||||
import { FileSystemHttpClient } from "../../test/src/core/FileSystemHttpClient";
|
import { FileSystemHttpClient } from "../../test/src/core/FileSystemHttpClient";
|
||||||
import { timeout } from "../../test/src/utils";
|
import { timeout } from "../../test/src/utils";
|
||||||
import { StubThreeRenderer } from "../../test/src/core/rendering/StubThreeRenderer";
|
|
||||||
import { Random } from "../core/Random";
|
import { Random } from "../core/Random";
|
||||||
import { Severity } from "../core/Severity";
|
import { Severity } from "../core/Severity";
|
||||||
import { StubClock } from "../../test/src/core/StubClock";
|
import { StubClock } from "../../test/src/core/StubClock";
|
||||||
|
import { STUB_THREE_RENDERER } from "../../test/src/core/rendering/StubThreeRenderer";
|
||||||
|
|
||||||
for (const path of [undefined, "/viewer", "/quest_editor", "/hunt_optimizer"]) {
|
for (const path of [undefined, "/viewer", "/quest_editor", "/hunt_optimizer"]) {
|
||||||
const with_path = path == undefined ? "without specific path" : `with path ${path}`;
|
const with_path = path == undefined ? "without specific path" : `with path ${path}`;
|
||||||
@ -28,7 +28,7 @@ for (const path of [undefined, "/viewer", "/quest_editor", "/hunt_optimizer"]) {
|
|||||||
new FileSystemHttpClient(),
|
new FileSystemHttpClient(),
|
||||||
new Random(() => 0.27),
|
new Random(() => 0.27),
|
||||||
new StubClock(new Date("2020-01-01T15:40:20Z")),
|
new StubClock(new Date("2020-01-01T15:40:20Z")),
|
||||||
() => new StubThreeRenderer(),
|
() => STUB_THREE_RENDERER,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(app).toBeDefined();
|
expect(app).toBeDefined();
|
||||||
|
@ -22,7 +22,7 @@ CameraControls.install({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface DisposableThreeRenderer extends THREE.Renderer, Disposable {}
|
export interface DisposableThreeRenderer extends THREE.WebGLRenderer, Disposable {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses THREE.js for rendering.
|
* Uses THREE.js for rendering.
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
import { HemisphereLight, PerspectiveCamera, Scene, Vector3 } from "three";
|
import {
|
||||||
|
DoubleSide,
|
||||||
|
HemisphereLight,
|
||||||
|
MeshBasicMaterial,
|
||||||
|
PerspectiveCamera,
|
||||||
|
Scene,
|
||||||
|
Vector3,
|
||||||
|
} from "three";
|
||||||
import { EntityType } from "../../core/data_formats/parsing/quest/entities";
|
import { EntityType } from "../../core/data_formats/parsing/quest/entities";
|
||||||
import { create_entity_type_mesh } from "./conversion/entities";
|
import { create_entity_type_mesh } from "./conversion/entities";
|
||||||
import { sequential } from "../../core/sequential";
|
import { sequential } from "../../core/sequential";
|
||||||
@ -40,19 +47,44 @@ export class EntityImageRenderer implements Disposable {
|
|||||||
(entity: EntityType): DisposablePromise<string> =>
|
(entity: EntityType): DisposablePromise<string> =>
|
||||||
this.entity_asset_loader.load_geometry(entity).then(geometry =>
|
this.entity_asset_loader.load_geometry(entity).then(geometry =>
|
||||||
this.entity_asset_loader.load_textures(entity).then(textures => {
|
this.entity_asset_loader.load_textures(entity).then(textures => {
|
||||||
|
// First render a flat version of the model with the same color as the
|
||||||
|
// background. Then render the final version on top of that. We do this to
|
||||||
|
// somewhat fix issues with additive alpha blending on a transparent background.
|
||||||
|
|
||||||
scene.remove(...scene.children);
|
scene.remove(...scene.children);
|
||||||
scene.add(light);
|
scene.add(light);
|
||||||
|
|
||||||
const entity_model = create_entity_type_mesh(entity, geometry, textures);
|
// Render the flat model.
|
||||||
scene.add(entity_model);
|
|
||||||
|
|
||||||
const b_sphere = entity_model.geometry.boundingSphere!;
|
const entity_model_bg = create_entity_type_mesh(
|
||||||
|
entity,
|
||||||
|
geometry,
|
||||||
|
[],
|
||||||
|
new MeshBasicMaterial({
|
||||||
|
color: 0x262626,
|
||||||
|
side: DoubleSide,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
scene.add(entity_model_bg);
|
||||||
|
|
||||||
|
const b_sphere = entity_model_bg.geometry.boundingSphere!;
|
||||||
camera.position.copy(camera_position);
|
camera.position.copy(camera_position);
|
||||||
camera.position.multiplyScalar(b_sphere.radius * camera_dist_factor);
|
camera.position.multiplyScalar(b_sphere.radius * camera_dist_factor);
|
||||||
camera.lookAt(b_sphere.center);
|
camera.lookAt(b_sphere.center);
|
||||||
|
|
||||||
this.renderer.render(scene, camera);
|
this.renderer.render(scene, camera);
|
||||||
|
|
||||||
|
scene.remove(entity_model_bg);
|
||||||
|
|
||||||
|
// Render the textured model.
|
||||||
|
|
||||||
|
const entity_model = create_entity_type_mesh(entity, geometry, textures);
|
||||||
|
scene.add(entity_model);
|
||||||
|
|
||||||
|
this.renderer.autoClearColor = false;
|
||||||
|
this.renderer.render(scene, camera);
|
||||||
|
this.renderer.autoClearColor = true;
|
||||||
|
|
||||||
return this.renderer.domElement.toDataURL();
|
return this.renderer.domElement.toDataURL();
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { QuestEntityModel } from "../../model/QuestEntityModel";
|
import { QuestEntityModel } from "../../model/QuestEntityModel";
|
||||||
import { BufferGeometry, DoubleSide, Mesh, MeshLambertMaterial, Texture } from "three";
|
import { BufferGeometry, DoubleSide, Material, Mesh, MeshLambertMaterial, Texture } from "three";
|
||||||
import { create_mesh } from "../../../core/rendering/conversion/create_mesh";
|
import { create_mesh } from "../../../core/rendering/conversion/create_mesh";
|
||||||
import {
|
import {
|
||||||
entity_type_to_string,
|
entity_type_to_string,
|
||||||
@ -31,12 +31,11 @@ export function create_entity_type_mesh(
|
|||||||
type: EntityType,
|
type: EntityType,
|
||||||
geometry: BufferGeometry,
|
geometry: BufferGeometry,
|
||||||
textures: Texture[],
|
textures: Texture[],
|
||||||
): Mesh {
|
default_material: Material = new MeshLambertMaterial({
|
||||||
const default_material = new MeshLambertMaterial({
|
|
||||||
color: is_npc_type(type) ? NPC_COLORS[ColorType.Normal] : OBJECT_COLORS[ColorType.Normal],
|
color: is_npc_type(type) ? NPC_COLORS[ColorType.Normal] : OBJECT_COLORS[ColorType.Normal],
|
||||||
side: DoubleSide,
|
side: DoubleSide,
|
||||||
});
|
}),
|
||||||
|
): Mesh {
|
||||||
const mesh = create_mesh(geometry, textures, default_material, false);
|
const mesh = create_mesh(geometry, textures, default_material, false);
|
||||||
mesh.name = entity_type_to_string(type);
|
mesh.name = entity_type_to_string(type);
|
||||||
return mesh;
|
return mesh;
|
||||||
|
@ -4,7 +4,7 @@ import { CharacterClassAssetLoader } from "../../loading/CharacterClassAssetLoad
|
|||||||
import { FileSystemHttpClient } from "../../../../test/src/core/FileSystemHttpClient";
|
import { FileSystemHttpClient } from "../../../../test/src/core/FileSystemHttpClient";
|
||||||
import { ModelView } from "./ModelView";
|
import { ModelView } from "./ModelView";
|
||||||
import { ModelRenderer } from "../../rendering/ModelRenderer";
|
import { ModelRenderer } from "../../rendering/ModelRenderer";
|
||||||
import { StubThreeRenderer } from "../../../../test/src/core/rendering/StubThreeRenderer";
|
import { STUB_THREE_RENDERER } from "../../../../test/src/core/rendering/StubThreeRenderer";
|
||||||
import { Random } from "../../../core/Random";
|
import { Random } from "../../../core/Random";
|
||||||
import { ModelStore } from "../../stores/ModelStore";
|
import { ModelStore } from "../../stores/ModelStore";
|
||||||
import { ModelToolBarView } from "./ModelToolBarView";
|
import { ModelToolBarView } from "./ModelToolBarView";
|
||||||
@ -26,8 +26,9 @@ test("Renders correctly.", () =>
|
|||||||
disposer.add(new ModelController(store)),
|
disposer.add(new ModelController(store)),
|
||||||
new ModelToolBarView(disposer.add(new ModelToolBarController(store))),
|
new ModelToolBarView(disposer.add(new ModelToolBarController(store))),
|
||||||
new CharacterClassOptionsView(disposer.add(new CharacterClassOptionsController(store))),
|
new CharacterClassOptionsView(disposer.add(new CharacterClassOptionsController(store))),
|
||||||
new ModelRenderer(store, new StubThreeRenderer()),
|
new ModelRenderer(store, STUB_THREE_RENDERER),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(view.element).toMatchSnapshot();
|
expect(view.element).toMatchSnapshot();
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { DisposableThreeRenderer } from "../../../../src/core/rendering/ThreeRenderer";
|
import { DisposableThreeRenderer } from "../../../../src/core/rendering/ThreeRenderer";
|
||||||
|
|
||||||
export class StubThreeRenderer implements DisposableThreeRenderer {
|
export const STUB_THREE_RENDERER: DisposableThreeRenderer = {
|
||||||
domElement: HTMLCanvasElement = document.createElement("canvas");
|
domElement: document.createElement("canvas"),
|
||||||
|
|
||||||
dispose(): void {} // eslint-disable-line
|
dispose(): void {}, // eslint-disable-line
|
||||||
|
|
||||||
render(): void {} // eslint-disable-line
|
render(): void {}, // eslint-disable-line
|
||||||
|
|
||||||
setSize(): void {} // eslint-disable-line
|
setSize(): void {}, // eslint-disable-line
|
||||||
}
|
} as any;
|
||||||
|
Loading…
Reference in New Issue
Block a user