-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Rendering improvements #160
Open
fallenoak
wants to merge
94
commits into
wowserhq:master
Choose a base branch
from
fallenoak:refactor/wmo-rendering
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* WMO materials are now shared between groups, provided the group referencing the material uses the material in the same way. Currently, this is defined as having the same interior/exterior flagging, the same batch type (A, B, or C), and the same index in the WMO root's MOMT chunk. * WMO materials are now created by the WMO root, rather than the individual groups. * WMO materials now properly copy the data out of MOMT, rather than directly manipulating it. This prevents issues that occurred when different WMO groups used the same material, but had different flags for interior / exterior.
* Removed branching logic from shaders in favor of preprocessor defines. * Switched from passing separate values for vertex color and alpha to passing single vec4. * Removed several now unnecessary uniforms from material. * Switched shaders to use .glsl suffix. * Moved shaders to dedicated subdirectory.
The Wrath of the Lich King client modifies MOCV values prior to passing them to the shader. The fixVertexColors() function attempts to implement approximately the same logic in Wowser. Additionally, root ambient color is now added (when appropriate) to vertex colors before being passed to the shader.
Also added an ifdef to still permit rendering without world lighting.
* All lighting is now calculated in the vertex shader. * Restored light modifier uniform functionality. * Changed expectation: all defines used as conditional checks are now expected to be defined (ie no more ifdef before if with conditional-use-only defines).
* Removed unused textureCount uniform. * Moved to Float32Array types for all vector uniforms. * Consolidated light and fog params into single vectors. * Corrected type attributes for uniforms (eg: 3fv, not f3v).
* Worker results can now take advantage of transferable objects when passing results back to the main thread. * Worker results now pass back objects with success and value properties. This replaces the array-based style used previously.
* Transferable typed arrays are now used for several buffer geometry attributes in WMO groups. On recent browsers, this greatly reduces the cost of transfering data back to the main thread when parsing WMO groups. * WMO roots now use a similar structure as WMO groups, although there's currently no transferable arrays in the root. * Loader logic has been separated out from the blueprint classes into dedicated loader classes. * The existing loader files that define the tasks that run on worker threads have been moved in to dedicated worker.js files.
* Switched from setTimeout to requestAnimationFrame. The latter seems more appropriate, since the queue is used to help smooth out loading to improve framerates. * Fixed a bug that resulted in always doing the minimum amount of work per queue run.
WMODefinition is used to set up transferable arrays of data on worker threads. WMOBlueprint is used to set up various objects (including rendering related objects) on the main thread. As of this change, blueprints are no longer confusingly used in two separate contexts. Additionally, the worker is back to being relatively small, and with far fewer dependencies.
* Changed WMO class to WMORoot to clarify its role. * Implemented proper (ie ref count based) unloading for WMO materials. * Eliminated texture count uniform from WMOMaterial. * Improved texture handling in WMOMaterial to support swapping textures after initial load. * WMO material defs now have a dedicated class. * Migrated WMO blueprint classes to be adjacent with the WMORoot and WMOGroup classes. * Removed some cruft from WMO blueprint classes.
* WMORootView and WMOGroupView are the classes expected to appear in the THREE.js scene. * Blueprint logic now lives in the WMORoot and WMOGroup classes. * WMOHandler creates the views necessary to render a given WMO in the THREE.js scene. The loaders no longer produce the view when loading.
The WorldLight class is meant to handle many or most of the functions served by the DayNight class in the retail client. Currently, it has the following abilities: * Calculation of sun direction based on time of day * Interpolation of color values based on time of day * Calculation of fog params based on time of day Additional functionality will be added in future commits.
The geometry on disk is fine as is (it's already Z-up). Placement of the WMOs will need to be altered to correctly compensate.
Note that THREE is now modular, and as such, requires modified import syntax. Instead of: import THREE from 'three'; if you want to import all of the library, it is now: import * as THREE from 'three';
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
NOTICE: PR and Description Work in Progress
This PR covers a wide range of rendering improvements for M2s, ADTs, and WMOs.
Read on for the key highlights.
Faster Loaders
Previously, all data parsed by Blizzardry for M2s, ADTs, and WMOs was copied back to the main thread using a structured clone. Unfortunately, the quantity of data being copied created a noticeable performance degradation. In particular, when the chunk render radius for the map would cause a new ADT tile to be pulled in, the main thread would hang for as much as 0.25 - 0.5 seconds.
As part of this PR, all loaders have been rewritten to make extensive use of transferable arrays. Typed arrays holding vertex, normal, color, and animation data are created on the worker threads. These typed arrays are then passed back to the main thread using the transferable feature of web workers. As a result, most data is no longer copied, but is instead passed by reference back to the main thread. This has eliminated the performance degradation, and generally reduced CPU load while navigating the world.
Simplified Geometry Data
Our old friend,
is now gone from M2 and WMO geometry.
In addition, vertices and normals are now read from disk verbatim. No more manipulation of axes / signs at load time.
Full M2 Shading
The overly broad M2 fragment and vertex shaders have been replaced by a full suite of shaders matching the shaders used by the WotLK client. Note that shader accuracy may still be somewhat off--but this is a journey, not a race.
Among other things, full shader support means env mapped textures are actually env mapped! Check out the shiny polish on the Ironforge steam tanks near the IF entrance, the sheen on the Northrend Penguin's feathers, or the fancy reflection on the glass tunnels at the midway point of the Deeprun Tram.
Vertex Shaders
Diffuse_T1
Diffuse_T1_T2
Diffuse_Env
Diffuse_T1_Env
Diffuse_Env_Env
Fragment Shaders
Combiners_Opaque
Combiners_Mod
Combiners_Opaque_Add
Combiners_Opaque_Mod2xNA_Alpha
Area Lighting
The exterior world is lit using something called area lights. These lights are effectively spheres with an inner and outer radius, and are used to fill in color data for things like sun diffuse, sun ambient, fog, sky bands, and etc.
The values are interpolated according to the time of day, with midnight being represented as
0.0
, and23:59:59.999
being represented as0.999
(repeating).Check out
WorldLight
for the implementation of area lighting and other functions handled by the WoW client'sDayNight
classes.Corrected M2 Billboarding
M2 billboarding now properly obeys transformed bone parents. This significantly cuts down on rendering oddities presented by billboarded M2s such as lamps.
Additionally, because M2 geometry is no longer rotated / inverted / etc, billboarding logic no longer involves sign changes.
Better WMO Rendering
WMO rendering has been extensively overhauled.
Self Illumination
Materials with
MOMT
flag0x10
enabled are self illuminated. These materials, typically things like windows on building exteriors, are lit using normal world light, a vertex color of0.5, 0.5, 0.5
, and an emissive color that is added based on a factor from the client's self illumination table.The emissive color used for self illumination in WMO materials is present in the
MOMT
data. On Wowdev.wiki, it is calledcolor0
.The self illumination table is present in the client as a set of static values. The self illumination factor can range from 0.0 to 1.0.
You can observe self illumination at work by paying a visit to Darkshire (or any other settlement, really). During the day time, exterior windows on things like the Darkshire inn will look like any other exterior material on the building. As night rolls in, the windows begin to glow, as if the interior of the inn was shining through the windows.
Vertex Color Attenuation
MOCV values in batch type A WMO group batches are attenuated based on distance to the nearest exterior portal. This attenuation is performed at runtime unless flag
0x01
is set on theMOHD
flags in the WMO root.This resolves issues like the overly dark triangle in inn entrances in old world inn WMOs.
Distance Culling
Map doodads are now culled based on bounding radius and distance from camera. As objects go out of view, they smoothly fade out. As objects come into view, they smoothly fade in. Fully out of view objects skip rendering, which increases framerates in particularly doodad-dense map regions.
Portal Culling
Special thanks: to @Deamon87 for guidance while implementing portal culling. He had the idea to use BSP trees to determine camera location relative to WMO groups, and his portal culling implementation in WebWoWViewer was one of the primary aids in figuring out how to implement this feature in Wowser.
The retail WoW client makes extensive use of something called portal culling to reduce scene complexity. In particular, capital city WMOs like Stormwind and Ironforge benefit heavily from the use of portal culling.
Portal culling works like this: