wowserhq / wowser

World of Warcraft in the browser using JavaScript and WebGL
MIT License
246 stars 63 forks source link

Add initial support for zone fog #85

Open fallenoak opened 8 years ago

fallenoak commented 8 years ago

Fog information is defined next to global lighting information across several DBCs:

The following workflow might be sufficient to get basic fog support working:

  1. Subscribe the WorldHandler to an area:change or chunk:change event (perhaps emitted by the player)
  2. The event should provide a few details, such as mapID, areaID (found in each ADT chunk), and position
  3. Select all matching light entries from Light.dbc by checking if the current player position is within the radius of the light entry
  4. Select nearest light entry and use as only light entry (to simplify approach for now)
  5. Identify matching rows in LightParams.dbc, LightIntBand.dbc, and LightFloatBand.dbc
  6. Update fog starting and ending distances in WorldHandler
  7. Create a timeline of intermediate color values between the current fog color and a target fog color
  8. Apply colors over time to fog color (perhaps using an animation track)

Considerations

fallenoak commented 8 years ago

In order to get pipeline/adt/chunk/material.js to obey scene fog, we need to add some default uniforms on the material. These uniforms need to be copied from ShaderLib's fog object. Standard materials get the uniforms by default, but ShaderMaterial does not.

Fortunately, once the default values are in place, three.js's renderer ensures that changes to scene.fog propagate to the material uniforms.

timkurvers commented 8 years ago

:+1: You mentioned something about a flat plane fog as opposed to circular, does that apply to both Fog and FogExp2?

fallenoak commented 8 years ago

:+1: You mentioned something about a flat plane fog as opposed to circular, does that apply to both Fog and FogExp2?

That was a result of:

float depth = gl_FragCoord.z / gl_FragCoord.w;

in the default THREE fog fragment shader. It turns out that's a somewhat clever-n-cheap way of getting a kind of 'depth'-- but the result is fairly jarring in our case, especially when camera movement is taken in to account. THREE.FogExp2 uses the same cheap strategy to obtain 'depth', but applies the fog color in a way that increases exponentially over distance, vs. linearly for THREE.Fog.

The approach I'm going with involves using the vertex shader to obtain the depth-from-camera of the vertex, and passing that along to the fragment shader:

...
varying vec3 vertexWorldPosition;
varying float cameraDistance;
...
void main()
  ...
  vertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
  cameraDistance = distance(cameraPosition, vertexWorldPosition);

I pass cameraDistance along to the fragment shader, and use that to determine fog mixing.