Opened 13 years ago

Closed 13 years ago

Last modified 8 years ago

#721 closed enhancement (fixed)

[PATCH] Optimise water renderer

Reported by: Philip Taylor Owned by: philip
Priority: Should Have Milestone: Alpha 7
Component: Core engine Keywords: simple
Cc: Rodolphe Ortalo Patch:

Description

TerrainRenderer::RenderWater seems very inefficient: when zoomed out it can take ~8msec/frame even with all the rendering disabled, and it does the rendering with glVertex3f calls.

Since water very rarely changes, I expect it'd be best to make CPatchRData store all the vertex data for water over its patch, and only recompute it when the terrain or water parameters change. Store the data in a vertex buffer. Use indexed quads.

As a bonus: If no visible patches have any water (i.e. they're all entirely above the water plane), don't render the reflection/refraction textures.

Attachments (5)

water_ro_r2.patch (38.2 KB ) - added by Rodolphe Ortalo 13 years ago.
patch with respect to trunk/ and revision 9001
water_ro_r2_r9062.patch (38.6 KB ) - added by Rodolphe Ortalo 13 years ago.
Patch with respect to trunk and revision 9062
water_ro_r3_r9066.patch (32.7 KB ) - added by Rodolphe Ortalo 13 years ago.
Patch with respect to trunk and revision 9066
water_ro_r4_r9073.patch (32.1 KB ) - added by Rodolphe Ortalo 13 years ago.
4th revision with respect to SVN rev9073
water_ro_r5_r9546.patch (32.2 KB ) - added by Rodolphe Ortalo 13 years ago.
Patch with respect to trunk and revision 9546

Download all attachments as: .zip

Change History (21)

comment:1 by Rodolphe Ortalo, 13 years ago

Submitting a patch for this issue. It moves water rendering to CPatchRData as described.

For fancy water, the vertex buffer is computed at build time and used permanently thereafter. For classical water, some initialization data is computed statically but some parts of the vertex buffer are recomputed for each frame (taking account camera position). In both cases, water is later drawn with indexed quads via glDrawElements  at render time (the terrain renderer iterates over visible patches).

Speed improvements seem (very) interesting, but I have not done precise benchmarking.

Additional water-related test methods have been added to PatchRData allowing to check if a given patch has any water, is entirely underwater or entirely out of water. (These tests are cheaply computed as a side effect of building the vertex buffer.)

As an addition, these checks are incorporated in the renderer main loop in order to avoid computing reflections or refractions when all visible patches are without water as suggested. But 2 additional optimizations are proposed here: not including underwater patches in reflections computation and not including fully emerged patches in refractions computation. The terrain renderer has also been adapted to allow these optimizations.

The perf. effect of these modifications is still rarely seen because the visible patches list sounds pretty over-estimated for the moment but could prove interesting when that list gets more precise.

The patch may not be perfect (includes a few commented-out lines for displaying some internal info.) but I welcome feedback.

by Rodolphe Ortalo, 13 years ago

Attachment: water_ro_r2.patch added

patch with respect to trunk/ and revision 9001

comment:2 by Rodolphe Ortalo, 13 years ago

Keywords: review added

NB: Also includes a small correction in water_high.vs vertex shader. It seems to me a typo had slipped in that shader (to be confirmed).

comment:3 by Rodolphe Ortalo, 13 years ago

Summary: Optimise water renderer[PATCH] Optimise water renderer

by Rodolphe Ortalo, 13 years ago

Attachment: water_ro_r2_r9062.patch added

Patch with respect to trunk and revision 9062

comment:4 by Rodolphe Ortalo, 13 years ago

New simplified revision 3 for patch and port to latest SVN. Removes tentative checks for eliminating emerged or underwater terrain from the reflection/refraction computation (under the assumption that it would better be done by culling for these).

by Rodolphe Ortalo, 13 years ago

Attachment: water_ro_r3_r9066.patch added

Patch with respect to trunk and revision 9066

comment:5 by Rodolphe Ortalo, 13 years ago

New revision 4:

  • merged simple and fancy vertex buffer struct to avoid complex mangling when switching dynamically between fancy and simple water via the "Enable Water Reflections" in-game option ;
  • added a (compiled in and currently unused) parameter that could allow in future to adjust water triangulation level of detail on patch.

by Rodolphe Ortalo, 13 years ago

Attachment: water_ro_r4_r9073.patch added

4th revision with respect to SVN rev9073

comment:6 by Philip Taylor, 13 years ago

A few random comments:

  • With non-fancy water, the texture doesn't appear to animate (it just scrolls a single frame). Looks like it sets period = 16.0f instead of period = 1.6.
  • SWaterVertex.m_UVs doesn't need to be stored explicitly. Shaders can do something like gl_TexCoord[0] = gl_Vertex.xz/repeatPeriod (if repeatPeriod is specified as a uniform) (looks like there's already a TODO for that). Non-shader can pass m_Position to glTexCoordPointer, and set up the transform in the glMatrixMode(GL_TEXTURE); section (like how losTexture.GetTextureMatrix() is handled) to do the scaling and the y/z component swap automatically.
  • SWaterVertex.m_Color should probably be a SColor4ub.
  • Then SWaterVertex is only 20 bytes. If it was specialised for fancy/simple modes then I think it'd only be 16, which would be nice, but probably not worth the complexity now.
  • BuildWaterVertices should do m_VBWater = 0 after it does g_VBMan.Release(m_VBWater), to avoid double-frees.
  • Emerged doesn't seem like an intuitive term to me - probably better to use something more explicit like AboveWater.
  • Probably get rid of the per-vertex fresnel effect for simple water - simple water will only be used in the compatibility mode for ~2% of users with very low-end hardware, so make it as simple and fast as possible (even if that makes it look ugly). Then there's no need to store m_WaterVertexData - just create m_VBWater and never update it.
  • m_WaterIndices should be stored in a vertex buffer (created with GL_ELEMENT_ARRAY_BUFFER). (There was a noticeable performance improvement when moving other terrain index data to vertex buffers, so it's a nice optimisation.)

comment:7 by Kieran P, 13 years ago

Keywords: simple review → simple, review

comment:8 by Kieran P, 13 years ago

Cc: Rodolphe Ortalo added
Owner: set to Rodolphe Ortalo

comment:9 by Kieran P, 13 years ago

Milestone: Alpha 5Alpha 6

by Rodolphe Ortalo, 13 years ago

Attachment: water_ro_r5_r9546.patch added

Patch with respect to trunk and revision 9546

comment:10 by Rodolphe Ortalo, 13 years ago

New revision 5 which should adress all the points outlined above in the last ticket comment, except the SWaterVertex.m_Color conversion to SColor4ub.

The removal of the per-vertex fresnel effect with simple water does not seem noticeable (for me).

Further feedback or testing welcome.

NB: Patch also includes also a small modif to source/lib/sysdep/gfx.cpp to allow for compilation of r9546 on linux.

comment:11 by Rodolphe Ortalo, 13 years ago

Status: newassigned

comment:12 by Kieran P, 13 years ago

Milestone: Alpha 6Alpha 7

comment:13 by Kieran P, 13 years ago

Owner: changed from Rodolphe Ortalo to philip
Status: assignednew

Work is included in or made obsolete by eihrul_'s frakenpatch. See http://lee.fov120.com/0ad-frankenpatch.diff . Ticket will be closed once frankenpatch is reviewed and committed.

comment:14 by Kieran P, 13 years ago

Type: taskenhancement

comment:15 by philip, 13 years ago

Resolution: fixed
Status: newclosed

(In [9814]) Graphics optimisations and features from eihrul. Add shadow filtering (PCF) option. Fix ugly shadow saturation in old lighting mode. Fix fancy water shader. Fix camera matrix computation. Support scissoring of camera frustum. Optimise vertex skinning. Inline various matrix functions. Support filtering of the list of submitted models before a rendering pass, for more precise culling. Optimise water renderer (fixes #721, based on patch by ortalo). Use scissoring when generating reflection/refraction textures. Skip reflection/refraction texture generation when no water is visible. Render alpha-blended objects differently (fixes #434). Reduce shadow swimming effects.

comment:16 by sanderd17, 8 years ago

Keywords: review removed
Note: See TracTickets for help on using tickets.