Improved rendering of entities that use additive blending in NPCs/Objects panels.

This commit is contained in:
Daan Vanden Bosch 2020-04-25 22:17:26 +02:00
parent eb5b539b6d
commit 78c18eb1e9
7 changed files with 53 additions and 22 deletions

View File

@ -151,7 +151,6 @@ Features that are in ***bold italics*** are planned but not yet implemented.
## 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
- [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

View File

@ -2,10 +2,10 @@ import { initialize_application } from "./index";
import { LogHandler, LogManager } from "../core/Logger";
import { FileSystemHttpClient } from "../../test/src/core/FileSystemHttpClient";
import { timeout } from "../../test/src/utils";
import { StubThreeRenderer } from "../../test/src/core/rendering/StubThreeRenderer";
import { Random } from "../core/Random";
import { Severity } from "../core/Severity";
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"]) {
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 Random(() => 0.27),
new StubClock(new Date("2020-01-01T15:40:20Z")),
() => new StubThreeRenderer(),
() => STUB_THREE_RENDERER,
);
expect(app).toBeDefined();

View File

@ -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.

View File

@ -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 { create_entity_type_mesh } from "./conversion/entities";
import { sequential } from "../../core/sequential";
@ -40,19 +47,44 @@ export class EntityImageRenderer implements Disposable {
(entity: EntityType): DisposablePromise<string> =>
this.entity_asset_loader.load_geometry(entity).then(geometry =>
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.add(light);
const entity_model = create_entity_type_mesh(entity, geometry, textures);
scene.add(entity_model);
// Render the flat 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.multiplyScalar(b_sphere.radius * camera_dist_factor);
camera.lookAt(b_sphere.center);
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();
}),
),

View File

@ -1,5 +1,5 @@
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 {
entity_type_to_string,
@ -31,12 +31,11 @@ export function create_entity_type_mesh(
type: EntityType,
geometry: BufferGeometry,
textures: Texture[],
): Mesh {
const default_material = new MeshLambertMaterial({
default_material: Material = new MeshLambertMaterial({
color: is_npc_type(type) ? NPC_COLORS[ColorType.Normal] : OBJECT_COLORS[ColorType.Normal],
side: DoubleSide,
});
}),
): Mesh {
const mesh = create_mesh(geometry, textures, default_material, false);
mesh.name = entity_type_to_string(type);
return mesh;

View File

@ -4,7 +4,7 @@ import { CharacterClassAssetLoader } from "../../loading/CharacterClassAssetLoad
import { FileSystemHttpClient } from "../../../../test/src/core/FileSystemHttpClient";
import { ModelView } from "./ModelView";
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 { ModelStore } from "../../stores/ModelStore";
import { ModelToolBarView } from "./ModelToolBarView";
@ -26,8 +26,9 @@ test("Renders correctly.", () =>
disposer.add(new ModelController(store)),
new ModelToolBarView(disposer.add(new ModelToolBarController(store))),
new CharacterClassOptionsView(disposer.add(new CharacterClassOptionsController(store))),
new ModelRenderer(store, new StubThreeRenderer()),
new ModelRenderer(store, STUB_THREE_RENDERER),
);
expect(view.element).toMatchSnapshot();
}));
})
);

View File

@ -1,11 +1,11 @@
import { DisposableThreeRenderer } from "../../../../src/core/rendering/ThreeRenderer";
export class StubThreeRenderer implements DisposableThreeRenderer {
domElement: HTMLCanvasElement = document.createElement("canvas");
export const STUB_THREE_RENDERER: DisposableThreeRenderer = {
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;