DYT/Tool/TritonSDK/PublicHeaders/Ocean.h

975 lines
63 KiB
C
Raw Normal View History

2024-12-25 14:48:51 +00:00
// Copyright (c) 2011-2021 Sundog Software, LLC. All rights reserved worldwide.
#ifndef TRITON_OCEAN_H
#define TRITON_OCEAN_H
/** \file Ocean.h
\brief Triton's Ocean model interface.
*/
#ifdef SWIG
#define TRITONAPI
%module TritonOcean
%include "carrays.i"
%include "cpointer.i"
%import "Environment.h"
%pointer_functions(float, floatp);
%array_functions( double, double_array )
SWIG_CSBODY_PROXY(public, public, SWIGTYPE)
SWIG_CSBODY_TYPEWRAPPER(public, public, public, SWIGTYPE)
%{
#include "Ocean.h"
using namespace Triton;
%}
#endif
#include "Environment.h"
#include "WakeGenerator.h"
#include "RotorWash.h"
#include "TidalStreamWake.h"
#pragma pack(push)
#pragma pack(8)
namespace Triton
{
class ProjectedGrid;
class WakeManager;
class ParticleSystemManager;
class SprayManager;
class DecalManager;
class Mutex;
class GodRays;
class Camera;
class WaterModelInitializationParams;
class ComplexNumber;
/** Enumerates the different water models available for simluating ocean waves. */
enum WaterModelTypes {
TESSENDORF, /** Tessendorf's ocean wave model with the Phillips wave spectrum, using fast Fourier transforms to simulate large numbers of waves at once. Good for open ocean when you value speed over accuracy. */
PIERSON_MOSKOWITZ, /** An FFT-powered Pierson-Moskowitz wave spectrum. Produces accurate waves that assume an infinite wind fetch. */
JONSWAP, /** The most accurate wave model, which takes wind fetch length into account. FFT-powered so it's still fast, but it responds more slowly when the wind conditions are changed. */
UNKNOWN_WATERMODEL
};
/** Enumerates the different shader programs used internally by Triton. */
enum Shaders {
WATER_SURFACE
, WATER_SURFACE_PATCH
, SPRAY_PARTICLES
, WAKE_SPRAY_PARTICLES
, GOD_RAYS
, WATER_DECALS
};
/** Enumerates the ocean quality settings used in Ocean::SetQuality() */
enum OceanQuality {
GOOD,
BETTER,
BEST
};
/// A structure describing a complex number, for use in Environment::OverrideFFTInputArray.
class TritComplex : public MemObject
{
public:
float real, imaginary;
};
/** The Ocean class allows you to configure and draw Triton's water simulation. */
class Ocean : public MemObject
{
public:
/** Creates an Ocean instance tied to the given Environment, using the specified wave model.
Make sure this is called only after your graphics context has been initialized and is active!
\param env A pointer to an Environment object created previously, which contains the environmental
conditions, coordinate system, camera, and rendering system used by the Ocean. The caller
is responsible for deleting this object after the Ocean is deleted.
\param type You may choose between the faster TESSENDORF implementation, or the more physically accurate
JONSWAP and PIERSON_MOSKOWITZ spectral models. JONSWAP is an extension of PIERSON_MOSKOWITZ
that accounts for wind "fetch length," so be sure to specify realistic distances (~100km)
traveled by the wind in your WindFetch objects to make the most of JONSWAP.
\param enableHeightTests Specifies whether the application will call Ocean::GetHeight() or not. If false,
Triton may be able to keep the ocean simulation entirely on the GPU leading to better
performance, but any calls to Ocean::GetHeight() may return 0. Set to true if you need
to read back height information from the water surface.
\param enableBreakingWaves Specifies whether shoreline effects with breaking waves are enabled. This does
create additional demands on the vertex and fragment programs and should only be enabled if
you're going to use them. Breaking waves require a floating-point height map containing
bathymetry data to be passed in via Environment::SetHeightMap(). \sa Environment::SetBreakingWavesParameters()
\param quality Specifies the tradeoff you want between wave detail and performance. Choose from GOOD, BETTER, or BEST.
\return An instance of Ocean that may be used for rendering. The caller is responsible for deleting
this object when finished. NULL may be returned if the ocean could not initialize itself;
in this case, enable the setting enable-debug-messages in resource/triton.config to get
more details on what went wrong sent to your debugger output window. Contact
support@sundog-soft.com with this output if necessary.
*/
static Ocean * TRITONAPI Create(Environment *env, WaterModelTypes type = JONSWAP, bool enableHeightTests = false,
bool enableBreakingWaves = false, OceanQuality quality = GOOD);
#ifndef SWIG
/** Creates an Ocean instance tied to the given Environment, using additional user-supplied OpenGL shader objects.
Make sure this is called only after your graphics context has been initialized and is active!
\param env A pointer to an Environment object created previously, which contains the environmental
conditions, coordinate system, camera, and rendering system used by the Ocean. The caller
is responsible for deleting this object after the Ocean is deleted.
\param userShaders A vector of OpenGL shader objects (created via glCreateShader) that will be linked into
all shader programs created by Triton. This allows you to provide your own shader functions to
Triton, which your modified Triton shaders may then call into. Triton::Ocean::GetShaderObject()
may be used to retrieve the linked shader programs, allowing you to set any uniforms your
functions require. The caller is responsible for deleting these custom shader object after
this Ocean object has been deleted.
\param type You may choose between the faster TESSENDORF implementation, or the more physically accurate
JONSWAP and PIERSON_MOSKOWITZ spectral models. JONSWAP is an extension of PIERSON_MOSKOWITZ
that accounts for wind "fetch length," so be sure to specify realistic distances (~100km)
travelled by the wind in your WindFetch objects to make the most of JONSWAP.
\param enableHeightTests Specifies whether the application will call Ocean::GetHeight() or not. If false,
Triton may be able to keep the ocean simulation entirely on the GPU leading to better
performance, but any calls to Ocean::GetHeight() may return 0. Set to true if you need
to read back height information from the water surface.
\param enableBreakingWaves Specifies whether shoreline effects with breaking waves are enabled. This does
create additional demands on the vertex and fragment programs and should only be enabled if
you're going to use them. Breaking waves require a floating-point height map containing
bathymetry data to be passed in via Environment::SetHeightMap(). \sa Environment::SetBreakingWavesParameters()
\param quality Specifies the tradeoff you want between wave detail and performance. Choose from GOOD, BETTER, or BEST.
\return An instance of Ocean that may be used for rendering. The caller is responsible for deleting
this object when finished. NULL may be returned if the ocean could not initialize itself;
in this case, enable the setting enable-debug-messages in resource/triton.config to get
more details on what went wrong sent to your debugger output window. Contact
support@sundog-soft.com with this output if necessary.
*/
static Ocean * TRITONAPI Create(Environment *env, const TRITON_VECTOR(unsigned int)& userShaders, WaterModelTypes type = JONSWAP,
bool enableHeightTests = false, bool enableBreakingWaves = false, OceanQuality quality = GOOD);
#endif
/** Virtual destructor. To ensure proper cleanup, be sure to delete your Ocean object before your Environment object. */
virtual ~Ocean();
/** Draws an infinite ocean surrounding the camera (as specified in the Environment object) for the simulated
conditions at the given time.
\param time The simulated point in time to render, in seconds. Note that this is an absolute time which
can be relative to any arbitrary point in time. It's not the delta time between frames.
In order to avoid precision issues; keep this value as small as possible. Best practice is
to make it relative to the application startup time.
\param depthWrites Whether the ocean will write to the depth buffer; you should probably leave this set
to true, since disabling it will lead to some artifacts. One technique for integrating
the ocean with terrain is to draw the ocean first with depth writes disabled, then
draw the terrain on top of it, thereby avoiding any depth buffer precision issues. Be sure
to remove or disable any existing ocean surfaces from your terrain database first if using
this technique. Be aware that disabling depth writes will lead to artifacts at certain camera
angles, since the waves won't be able to depth-sort against themselves; a better and simpler
approach would be to leave depthWrites on, and then clear the depth buffer after calling Draw
early in your frame.
\param drawWater Whether the water surface should be drawn in this call. You may want to draw the water
(which is non-transparent) separately from the spray particles (which are transparent.) This parameter,
together with drawParticles, lets you choose what combination of water and particles should be drawn
with this call.
\param drawParticles Whether spray particles from breaking waves, rotor wash, impacts, etc. are drawn with this
call.
\param context An optional context, depending on the rendering system in question. For example, you can
render in DX 11 into a command list in a deferred context and execute the command list on
the immediate context at a later time.
\param camera An optional camera. If you have multiple views, you can pass in the camera directly. This is the preferred
method than setting the view using Environment class methods: Environment::SetCameraMatrix(), Environment::SetProjectionMatrix().
In conjunction with multiple contexts, you can do multi-threaded rendering as well (different draw calls can be in different threads).
However, for multiple contexts, multiple-threads and scenarios like stereo-rendering where the left/right views don't differ by much,
its faster to use Ocean::DrawConcurrent(). See Ocean::DrawConcurrent().
*/
virtual void TRITONAPI Draw(double time, bool depthWrites = true, bool drawWater = true, bool drawParticles = true, void* context = 0, const Camera* camera = 0);
/** Draws an infinite ocean surrounding the camera (as specified in the Environment object) for the simulated
conditions at the given time. This is a specialized method for any variation of multi-threaded, multi-context or multi-view
scenarios. If for example you have multiple contexts, each with a different view, you call this method from different threads
drawing into different contexts (contexts here means not a separate window necessarily but for example a deferred DX11 context or
an OpenGL command list based drawing application with multiple views).
Following this you *must* call Ocean::PostDrawAll() after all the concurrent draws have completed from the main thread.
Ocean::PostDrawConcurrent() is automatically called when using the Ocean::Draw() method. This method is inherently thread safe
, so the thread-safe option in Triton.config is ignored.
\param time The simulated point in time to render, in seconds. Note that this is an absolute time which
can be relative to any arbitrary point in time. It's not the delta time between frames.
In order to avoid precision issues; keep this value as small as possible. Best practice is
to make it relative to the application startup time.
\param depthWrites Whether the ocean will write to the depth buffer; you should probably leave this set
to true, since disabling it will lead to some artifacts. One technique for integrating
the ocean with terrain is to draw the ocean first with depth writes disabled, then
draw the terrain on top of it, thereby avoiding any depth buffer precision issues. Be sure
to remove or disable any existing ocean surfaces from your terrain database first if using
this technique. Be aware that disabling depth writes will lead to artifacts at certain camera
angles, since the waves won't be able to depth-sort against themselves; a better and simpler
approach would be to leave depthWrites on, and then clear the depth buffer after calling Draw
early in your frame.
\param drawWater Whether the water surface should be drawn in this call. You may want to draw the water
(which is non-transparent) separately from the spray particles (which are transparent.) This parameter,
together with drawParticles, lets you choose what combination of water and particles should be drawn
with this call.
\param drawParticles Whether spray particles from breaking waves, rotor wash, impacts, etc. are drawn with this
call.
\param context An optional context, depending on the rendering system in question. For example, you can
render in DX 11 into a command list in a deferred context and execute the command list on
the immediate context at a later time.
\param camera An optional camera. In conjunction with multiple contexts, you can do multi-threaded rendering as well using this method, and is
the preferred method when cameras don't differ much (e.g. left/right stereo rendering). The sequence of calls is:
Environment::SetProjectionMatrix() -> for the main view from which the left/right views are derived
Environment::SetCameraMatrix() -> for the main view from which the left/right views are derived
Environment::UpdateSimulation() -> needs to be called only once!
Ocean::DrawConcurrent(left camera)
Ocean::DrawConcurrent(right camera)
Ocean::PostDrawConcurrent
*/
virtual void TRITONAPI DrawConcurrent(double time, bool depthWrites = true, bool drawWater = true, bool drawParticles = true, void* context = 0, const Camera* camera = 0);
/** Method that *must* be called from the main thread after all Ocean::DrawConcurrent calls have completed
to give a chance to Triton to do some post draw house keeping after the draw calls have completed. This
is automatically called when Ocean::Draw is uesd.
*/
void TRITONAPI PostDrawConcurrent();
/** Sets the shaders and state necessary for rendering a user-provided patch of geometry as water. Use this if you
don't want Triton to draw an infinite ocean using Ocean::Draw(), but only want to draw your own water patches.
All that's required is the rendering of vertex data containing 3D position data following this call, and
a call to Ocean::UnsetPatchShader() must be called after you've drawn your water geometry.
The geometry drawn should be flat, relative to sea level. Our shaders will displace the vertices rendered
and apply all the textures and reflections to make it look like water. Remember to call Ocean::SetDepth() if
you are drawing an area of shallow water and don't want this patch to look like open ocean.
For best results, ensure your depth tests are set to "less than or equal" to ensure proper sorting of
Triton's waves against each other.
Note that particle-based spray effects won't be rendered when you're drawing your own geometry, all this does
is shade the geometry you draw following this call to make your geometry look like water. You'll still get
foam, reflections, and refractions. This method only works with TESSENDORF waves.
If you are using a WGS84 or SPHERICAL CoordinateSystem, our shaders assume that your mesh is positioned relative
to the center of the Earth being at 0, 0, 0. To preserve precision, your vertices when transformed by the modelMatrix
provided should be relative to the camera position. Our shaders are compiled at runtime, so you may modify them
if your data is of an unusual format. Look for the shaders ending with -patch.fx or -patch.glsl inside the Resources
directory; these are used only by this method.
If your application is using Triton's volumetric decal features, you must draw your patch a second time with the
depthPass parameter set to "true" on both SetPatchShader() and UnsetPatchShader(). This will generate a depth
texture needed for projecting the volumetric decals properly.
OpenGL users should ensure that your vertex array is bound prior to calling this method; DirectX11 users
should set their vertex buffer with the input assembly stage prior to calling this method.
\sa UnsetPatchShader()
\sa SetPatchMatrix()
\param time The simulated point in time to render, in seconds. Note that this is an absolute time which
can be relative to any arbitrary point in time. It's not the delta time between frames.
TAKE CARE that this value is not too large; you may want to make it relative to your
application start time, or fmod it with the number of seconds in one day for example.
The GPU wave simulation is single precision, and very large time values will result in
jittery wave animations.
\param vertexStride The number of bytes between vertices in your vertex array. This is only used in OpenGL 3.2+
and DirectX11 to allow binding of your vertex array with the appropriate vertex attribute in
our shaders.
\param positionOffset The number of bytes from the start of each vertex to the x,y,z floating point position
data. Used only in OpenGL 3.2+.
\param doublePrecisionVertices Pass in true if your vertex data is "double" precision, or false for "float" single
precision data. Only relevant in OpenGL 3.2 or newer.
\param modelMatrix Receives an array of 16 doubles defining a 4x4 model matrix for the ocean patch. If set to NULL,
an identity matrix is assumed.
\param decalPass If you are using Triton::Decal objects, or the decal option on the rotor wash effect, you must
draw your patch of water a second time while passing true for the decalPass parameter on
SetPatchShader() and UnsetPatchShader(). This will generate the depth texture that volumetric
decals need in order to project themselves properly onto the water surface. If SetPatchShader
returns false while decalPass is true, then no decals are in view and you should not proceed
to re-draw your ocean geometry. You do still need to balance this call with a call to
UnsetPatchShader() no matter what, however.
\param context An optional context, depending on the rendering system in question. For example, you can
render in DX 11 into a command list in a deferred context and execute the command list on
the immediate context at a later time.
\param camera An optional camera for the view being rendered.
\return True if the state was successfully set and drawing may continue.
*/
virtual bool TRITONAPI SetPatchShader(double time, int vertexStride, int positionOffset, bool doublePrecisionVertices,
const double *modelMatrix = 0, bool decalPass = false, void* context = 0, const Camera* camera = 0);
/** If you are drawing many of your own water meshes using SetPatchShader() at once, it will be much faster to call
SetPatchShader() once, then call SetPatchMatrix() for each individual mesh to set its location, followed by
UnsetPatchShader() when you're done drawing all of them. This is only useful if you are drawing many water patches
in the same scene, but it can have a large performance benefit if so.
\param modelMatrix Receives an array of 16 doubles defining a 4x4 model matrix for the ocean patch. If set to NULL,
an identity matrix is assumed.
\param context An optional context, depending on the rendering system in question. For example, you can
render in DX 11 into a command list in a deferred context and execute the command list on
the immediate context at a later time.
\param camera An optional camera for the view being rendered.
\return True if the matrix was set successfully.
*/
virtual bool TRITONAPI SetPatchMatrix(const double *modelMatrix, void* context = 0, const Camera* camera = 0);
/** Restores the graphics state prior to a previous call to Ocean::SetPatchShader(). Every call to Ocean::SetPatchShader()
must be matched with a call to Ocean::UnsetPatchShader() following the drawing of any user-defined patches of water.
If you want particle-based spray effects, you may optionally pass in a timestamp and bounding box for your patch to
enable these effects.
\param time The current time, in seconds, used for particle animations. Optional; set to 0.0 if unused.
\param patchBounds A bounding box defining the bounds of your patch, used for particle animations. Optional.
\param decalPass If you are using Triton::Decal objects, or the decal option on the rotor wash effect, you must
draw your patch of water a second time while passing true for the decalPass parameter on
SetPatchShader() and UnsetPatchShader(). This will generate the depth texture that volumetric
decals need in order to project themselves properly onto the water surface. The decals themselves
will also be rendered at this point.
\param context An optional context, depending on the rendering system in question. For example, you can
render in DX 11 into a command list in a deferred context and execute the command list on
the immediate context at a later time.
\param camera An optional camera for the view being rendered.
\sa SetPatchShader()
*/
virtual void TRITONAPI UnsetPatchShader(double time = 0.0, const TBoundingBox* patchBounds = 0, bool decalPass = false, void* context = 0, const Camera* camera = 0);
#ifndef SWIG
/** OpenGL only: Reload the underlying shader programs, linking in a new list of user-supplied shader object ID's with each program.
\param reloadSurface Indicates whether the shaders used for the water surface should be recompiled and relinked.
\param reloadWakes Indicates whether the shaders for wake spray effects should be recompiled and relinked.
\param reloadSprays Indicates whether the shaders for spray effects on high waves should be recompiled and relinked.
\param reloadDecals Indicates whether the shaders for ocean decals should be recompiled and relinked.
\param reloadGodRays Indicates whether the shaders for underwater crepuscular rays should be recompiled and relinked. */
virtual bool ReloadShaders(const TRITON_VECTOR(unsigned int)& shaders, bool reloadSurface = true,
bool reloadWakes = true, bool reloadSprays = true, bool reloadDecals = true, bool reloadGodRays = true);
#endif
/** In OpenGL, this must be called with each set of context and camera that you intend to render with
See the OpenGL multi-contexts sample*/
virtual bool Initialize(void* context, const Camera* camera);
/** Updates the underlying wave simulation; calling this is optional and only necessary if you wish to perform
physics updates from a pass or thread different from the rendering pass or thread. If UpdateSimulation() is
not called prior to Draw() or SetPatchShader(), then Draw() or SetPatchShader() will call it automatically.
A mutex is enforced between this method and the Draw(), SetPatchShader(), and GetHeight() methods. A valid GL
context must still be present while calling this.
\param time The simulated point in time to render, in seconds. Note that this is an absolute time which
can be relative to any arbitrary point in time. It's not the delta time between frames.
TAKE CARE that this value is not too large; you may want to make it relative to your
application start time, or fmod it with the number of seconds in one day for example.
The GPU wave simulation is single precision, and very large time values will result in
jittery wave animations.
\param camera An optional camera. Simulations are view dependent. If you have multiple views and are
doing the updates manually using this method, you must specify the camera in that case.
\sa DrawConcurrent()
*/
virtual void TRITONAPI UpdateSimulation(double time, const Camera* camera = 0);
/** DirectX9 users must call D3D9DeviceLost() in response to lost devices, prior to resetting the device. A lost
device may occur when the user locks and unlocks a system or changes the monitor resolution, and must be
explicitly handled under DX9. Call D3D9DeviceReset() once the device has been recreated. */
void TRITONAPI D3D9DeviceLost();
/** DirectX9 users must call D3D9DeviceReset() in response to device resets done in response to lost devices.
You must have called D3D9DeviceLost() first in response to the lost device. */
void TRITONAPI D3D9DeviceReset();
/** Retrieves the choppiness setting of the Ocean, which controls how peaked the waves are. \sa SetChoppiness() */
float TRITONAPI GetChoppiness() const;
/** Set the choppiness of the waves, which controls how peaked the waves are. \sa GetChoppiness()
\param chop The choppiness parameter; 0.0 yields no chop, 3.0 yields strong chop. Values that are too
high may result in wave geometry folding over itself, so take care to set reasonable
values.
*/
void TRITONAPI SetChoppiness(float chop);
/** Retrieves the looping period of the Ocean, which define time after which wave simulation repeats. \sa SetLoopingPeriod() */
float TRITONAPI GetLoopingPeriod() const;
/** Set the looping period of the Ocean, which define time after which wave simulation repeats. \sa GetLoopingPeriod()
If set to non zero, wave sumulation loops after that period. 0 is the default. FFT Wave model uses mixture of compound
frequency waves. When Period value is set, these compound frequencies are constrained to be a multiply of looping frequence.
Hence period may affect the wave shapes. General rule is to use highest possible period length to minimize the imapact
on wave field realism. We recommend periods larger than 30 seconds.
*/
void TRITONAPI SetLoopingPeriod(float loopingPeriod);
/** Retrieves the simulated depth of the water in world units, and the surface
normal of the sea floor, both at the current camera position. Only returns
the values set by SetDepth(). \sa SetDepth()
\param floorNormal A reference to a Vector3 to retrieve the surface normal
of the sea floor as set by SetDepth().
\param camera An optional camera. Some computations of depth are camera dependent. So
you need to specify the camera in question.
\return The depth of the sea floor at the camera position, as set by SetDepth().
*/
float TRITONAPI GetDepth(Triton::Vector3& floorNormal, const Camera* camera = 0) const;
/** Sets the simulated depth of the water in world units at the camera position,
and the slope of the sea floor as specified by its surface normal at the
camera position. This information is used to interpolate the water depth
at various positions in the scene, affecting the transparency of the water
as well as the height of the waves. Avoid changing this every frame for
performance reasons. \sa GetDepth()
\param depth The depth of the water, in world units, at the camera position.
Negative values will be clamped to zero. For open ocean, either
do not call this method or set depth to a large number (like 1000).
\param floorNormal The surface normal of the sea floor at the camera position.
The point defined by the depth parameter under the camera position
together with this normal will define a plane that approximates the
position of the sea floor surrounding the current location.
\param camera An optional camera. Some computations of depth are camera dependent. So
you need to specify the camera in question.
*/
void TRITONAPI SetDepth(float depth, const Triton::Vector3& floorNormal, const Camera* camera = 0);
/** Enables or disables wireframe rendering of the ocean's mesh.
\param wireframeOn Set to true to render in wireframe mode, false to render normally.
*/
void TRITONAPI EnableWireframe(bool wireframeOn);
/** Returns a description of the FFT transform being used, if a FFT water model
is active. */
const char * TRITONAPI GetFFTName() const;
/** Returns the number of triangles rendered by the underlying projected grid. */
unsigned int TRITONAPI GetNumTriangles() const;
/** Retrieves an underlying shader object used to render the water. If you make modifications
to our shaders to add additional effects, you can use this in order to pass your own
uniform variables into the shaders. Depending on the renderer you're using, you'll need
to cast this to a GLuint, ID3DXEffect, or ID3DX11Effect.
If you are shading the water surface, be sure to pass uniforms to both WATER_SURFACE and
WATER_SURFACE_PATCH. The latter is used when the camera is near the water surface.
\param shaderProgram Specifies which shader program you want to retrieve: WATER_SURFACE,
WATER_SURFACE_PATCH, SPRAY_PARTICLES, WAKE_SPRAY_PARTICLES, or WATER_DECALS.
\param context Shaders are context and camera specific. Internally, there is a different
shader for each key of context (DX 11 command list/deferred context or OpenGL Stream) and
Camera. This is so as to support multi-threaded rendering seamlessly. Therefore, you must
provide context and camera to get the shader in question for that key of context and camera
If no context is specified, Triton will use the immediate context for DX 11 and the immediate
OpenGL stream for OpenGL. If no camera is specified, the default environment camera is used
as as part of the key.
\param camera Shaders are context and camera specific. Internally, there is a different
shader for each key of context (DX 11 command list/deferred context or OpenGL Stream) and
Camera. This is so as to support multi-threaded rendering seamlessly. Therefore, you must
provide context and camera to get the shader in question for that key of context and camera
If no context is specified, Triton will use the immediate context for DX 11 and the immediate
OpenGL stream for OpenGL. If no camera is specified, the default environment camera is used
as as part of the key.
\return The GLuint, ID3DXEffect, or ID3DX11Effect representing the shader object,
or 0 if no shader is loaded.
*/
ShaderHandle TRITONAPI GetShaderObject(Shaders shaderProgram, void* context = 0, const Camera* camera = 0) const;
// Retrives the underlying WakeManager. For internal use only.
WakeManager * TRITONAPI GetWakeManager() {
return wakeManager;
}
// Retrieves the underlying DecalManager. For internal use only.
DecalManager * TRITONAPI GetDecalManager() {
return decalManager;
}
/** Applies a decal texture to the dynamic ocean surface, useful for effects involving films, debris, or foam
on the water.
\param texture The texture to apply to the water surface. Under OpenGL, this must be a GLuint indicating the ID of the GL_TEXTURE_2D returned from
glGenTextures. Under DirectX9, this must be a LPDIRECT3DTEXTURE9. Under DirectX11, this must be a
ID3D11ShaderResourceView pointer with an underlying ViewDimension of D3D11_SRV_DIMENSION_TEXTURE2D.
\param size The size of the decal, in world units.
\param position The center position of the decal on the water surface, in world units.
\return An identifier for this decal, which may be passed to RemoveDecal() to later dispose of this decal.
*/
DecalHandle TRITONAPI AddDecal(TextureHandle texture, float size, const Vector3& position);
/** Scales an existing decal in width and depth at runtime.
\param decal A decal handle retrieved from a previous call to AddDecal().
\param scaleWidth The scale factor for the decal's width (ie, 0.5 = half size, 2.0 = double.)
\param scaleDepth The scale factor for the decal's depth.
*/
void TRITONAPI ScaleDecal(DecalHandle decal, float scaleWidth, float scaleDepth);
/** Moves an existing decal to the given location. */
void TRITONAPI MoveDecal(DecalHandle decal, const Vector3& position);
/** Rotates an existing decal by the given amount in radians.
\param decal A decal handle retrieved from a previous call to AddDecal().
\param radians The rotation of the decal, given in radians.
*/
void TRITONAPI RotateDecal(DecalHandle decal, double radians);
/** Sets a decal's alpha blending amount (default is 1.0.)
\param decal A decal handle retrieved from a previous call to AddDecal().
\param alpha The alpha value applied to the decal texture. 0 = transparent, 1.0 = opaque.
*/
void TRITONAPI SetDecalAlpha(DecalHandle decal, float alpha);
/** Removes a decal texture previously applied with AddDecal(). */
void TRITONAPI RemoveDecal(DecalHandle decal);
/** Retrieves the height and normal of the ocean surface at the intersection point of the given ray. The
results of this method are only valid if Ocean::Create() was called with the parameter
enableHeightReads set to true. The height returned is relative to sea level, as specified
by Triton::Environment::SetSeaLevel(). For example, the crest of a one-meter-high wave will
always return a height of one meter, irrespective of the environment's sea level height.
Depending on the application, you may want to add in the result of
Triton::Environment::GetSeaLevel() to the height returned.
\param point The origin of the ray to test the height against.
\param direction The normalized direction vector of the ray.
\param height Receives the height at the ray's intersection with the ocean, if an
intersection was found.
\param normal Receives a normalized unit vector pointing in the direction of the normal
vector of the sea surface at the intersection point.
\param visualCorrelation Set to true in order to have the height returned match the visuals,
which dampen height offsets with distance to avoid sampling artifacts. To return
the true wave height at the given location, set to false.
\param includeWakes Whether this height query should include waves from rotor wash
and impacts in its results. Ship Kelvin wakes will be approximated.
\param highResolution If true, the ocean grid points surrounding the intersection point will be
sampled and interpolated. If false, the height will be based on the nearest
grid point alone.
\param threadSafe Whether a mutex will be locked with this call to ensure thread safety with
Ocean::Draw(). If you are conducting many intersection tests and are only single
threaded, pass false for better performance. You may also use Ocean::Lock() and
Ocean::Unlock() to manually lock and unlock the mutex surrounding many GetHeight calls.
\param intersectionPoint If you need an intersection point on the water surface and not just a height
value, pass in a pointer to a Triton::Vector3 object and we'll populate it with the result.
Otherwise, pass NULL. NOTE that this intersection is computed as the intersection of the
ray with sea level, with the height of the waves at that point added in. It will become
less accurate as your ray becomes more oblique with the ocean surface. For accurate
intersection tests including waves from oblique angles, see Triton::Ocean::GetWavesIntersection().
\param autoFlip If true, GetHeight() will flip your direction vector automatically if it does not intersect
the water surface at all, in an attempt to return an intersection. This lets you not worry
about whether your origin point is above or below the water surface. If you'd rather just
have GetHeight() return false when your direction is pointing away from the water, set
autoFlip to false instead.
\param camera An optional camera. Some computations of height are camera dependent. So
you need to specify the camera in question. This is particularly needed if you are syncing
height queries in a NO_RENDERER channel with other visual channels; you must pass
consistent camera positions for consistent results.
\return True if an intersection was found, false if not. If a height map was passed in using
Environment::SetHeightMap(), this will return false if the intersection is over terrain.
*/
bool TRITONAPI GetHeight(const Vector3& point, const Vector3& direction, float& height, Vector3& normal,
bool visualCorrelation = true, bool includeWakes = true, bool highResolution = true,
bool threadSafe = true, Vector3 *intersectionPoint = 0, bool autoFlip = true, const Camera* camera = 0);
#ifndef SWIG
/** This is a batch version of Triton::Ocean::GetHeight(), which will avoid stalling the OpenGL
pipeline waiting for synchronization when retrieving heights for each point. This can be more efficient
when retrieving many height lookups at once, but its optimizations are only useful under OpenGL.
This method works in our internal tests, but is considered experimental for now.
Retrieves the height and normal of the ocean surface at the intersection points of the given rays. The
results of this method are only valid if Ocean::Create() was called with the parameter
enableHeightReads set to true. The heights returned are relative to sea level, as specified
by Triton::Environment::SetSeaLevel(). For example, the crest of a one-meter-high wave will
always return a height of one meter, irrespective of the environment's sea level height.
Depending on the application, you may want to add in the result of
Triton::Environment::GetSeaLevel() to the height returned.
\param points A vector of the origins of the rays to test the height against.
\param directions A vector of the normalized direction vectors of each ray. This vector
must match up with the points vector passed in.
\param heights A reference to a vector of floats, which receives the heights at each
ray's intersection with the ocean, if an intersection was found. These will be returned
in the same order as the points passed in, as is the normal and intersectionPoints results.
\param normals A reference to a vector of Vector3 objects, which receives normalized unit
vectors pointing in the direction of the normal vector of the sea surface at each intersection point.
\param intersectionPoints A reference to a vector of Vector3 objects, which receives each intersection
point on the water surface. NOTE that this intersection is computed as the intersection of the
ray with sea level, with the height of the waves at that point added in. It will become
less accurate as your ray becomes more oblique with the ocean surface. For accurate
intersection tests including waves from oblique angles, see Triton::Ocean::GetWavesIntersection().
\param visualCorrelation Set to true in order to have the height returned match the visuals,
which dampen height offsets with distance to avoid sampling artifacts. To return
the true wave height at the given location, set to false.
\param includeWakes Whether this height query should include waves from rotor wash
and impacts in its results. Ship Kelvin wakes won't be included.
\param highResolution If true, the ocean grid points surrounding the intersection point will be
sampled and interpolated. If false, the height will be based on the nearest
grid point alone.
\param threadSafe Whether a mutex will be locked with this call to ensure thread safety with
Ocean::Draw(). If you are conducting many intersection tests and are only single
threaded, pass false for better performance. You may also use Ocean::Lock() and
Ocean::Unlock() to manually lock and unlock the mutex surrounding many GetHeight calls.
\param autoFlip If true, GetHeight() will flip your direction vector automatically if it does not intersect
the water surface at all, in an attempt to return an intersection. This lets you not worry
about whether your origin point is above or below the water surface. If you'd rather just
have GetHeight() return false when your direction is pointing away from the water, set
autoFlip to false instead.
\param camera An optional camera. Some computations of height are camera dependent. So
you need to specify the camera in question. This is particularly needed if you are syncing
height queries in a NO_RENDERER channel with other visual channels; you must pass
consistent camera positions for consistent results.
\return True if valid heights, normals, and intersections have been populated for every point passed in.
If false is returned, the results cannot be assumed to be valid for any point queried and you may want to
fall back to Ocean::GetHeight() for each individual point. If a height map was provided to Triton,
true will be returned even if some points are over terrain and not over water.
*/
bool TRITONAPI GetBatchHeight(const TRITON_VECTOR(Vector3) points, const TRITON_VECTOR(Vector3) directions, TRITON_VECTOR(float)& heights,
TRITON_VECTOR(Vector3)& normals, TRITON_VECTOR(Vector3)& intersectionPoints,
bool visualCorrelation = true, bool includeWakes = true, bool highResolution = true,
bool threadSafe = true, bool autoFlip = true, const Camera* camera = 0);
#endif
/** Retrieves an intersection between a ray and the ocean surface, taking waves and wakes into account. This method can account
for rays at an oblique angle to the ocean; internally it marches along the ray at increments defined by the "precison"
parameter, stopping at the point where a height test directly underneath each step is at or above the height of the step.
To maximize performance, the ray marching starts at the point where the current maximum wave height could possibly
cause an intersection. However, this is still an expensive function to call. If your rays are perpendicular to the ocean
surface, you will get much better performance by using Triton::Ocean::GetHeight() instead and the intersectionPoint it returns.
In the case of perpendicular rays, a quick height map lookup is all that's needed, and you don't need the complexity of this method.
If you don't need to take waves and wakes into account, Triton::Ocean::GetIntersection() will be even faster.
You can make your own trade-offs between performance and precision by using the "precision" parameter.
\param point The origin of the ray to intersect with.
\param direction The normalized direction vector of the ray.
\param normal Receives a normalized unit vector pointing in the direction of the normal
vector of the sea surface at the intersection point.
\param intersectionPoint Receives the intersection of the ray with the water surface, within the precision requested.
\param precision The size of the steps taken along the ray, searching for an intersection with the water surface.
Increasing this will improve performance.
\param visualCorrelation Set to true in order to have the height returned match the visuals,
which dampen height offsets with distance to avoid sampling artifacts. To return
the true wave height at the given location, set to false.
\param threadSafe Whether a mutex will be locked with this call to ensure thread safety with
Ocean::Draw(). If you are conducting many intersection tests and are only single
threaded, pass false for better performance. You may also use Ocean::Lock() and
Ocean::Unlock() to manually lock and unlock the mutex surrounding many GetHeight calls.
\param camera An optional camera. Some computations of height are camera dependent. So
you need to specify the camera in question. This is particularly needed if you are syncing
height queries in a NO_RENDERER channel with other visual channels; you must pass
consistent camera positions for consistent results.
\return True if an intersection was found, false if not. If a height map was passed in using
Environment::SetHeightMap(), this will return false if the intersection is over terrain.
*/
bool TRITONAPI GetWavesIntersection(const Vector3& point, const Vector3& direction, Vector3& normal, Vector3& intersectionPoint,
double precision = 0.1, bool visualCorrelation = true, bool threadSafe = true,
const Camera* camera = 0);
/** Retrieves the intersection, if any, between a ray and the ocean surface. This method does NOT take
wave heights into account; use Ocean::GetHeight() for that level of resolution.
\param point The origin of the ray to intersect with, in world coordinates.
\param direction The direction of the ray to intersect with, in world coordinates.
\param intersection Receives the intersection point if an intersection exists.
\param camera An optional camera. Some computations of intersection are camera dependent. So
you need to specify the camera in question.
\return True if an intersection was found, false if not. If height map data has been given using
Environment::SetHeightMap(), false will also be returned if the intersection point is over terrain.
*/
bool TRITONAPI GetIntersection(const Vector3& point, const Vector3& direction, Vector3& intersection, const Camera* camera = 0);
/** Retrieves the wave direction. Normally this is the same as the wind direction, but in shallow water
it will align with the slope of the sea floor as specified in SetDepth(). */
float TRITONAPI GetWaveHeading() const {
return waveHeading;
}
/** Enables or disables spray particle effects on breaking waves. This does incur a performance
penalty, so if you need faster performance, try disabling spray effects or even disable it
entirely with the fft-enable-spray config setting in resources/Triton.config. */
void TRITONAPI EnableSpray(bool enable);
/** Returns if spray particle effects on breaking waves are enabled, which they are by default.
\sa EnableSpray(). */
bool TRITONAPI SprayEnabled() const {
return sprayEnabled;
}
/** Modifies the color used for refracted light rays that go into deep water. You can use this to modify the
color of the water in areas that are not purely reflective.
\param refractionColor the RGB color value of the deep water color; each component should be in the range 0-1.
*/
void TRITONAPI SetRefractionColor(const Vector3& refractionColor);
/** Returns the color of light refracted into the water.
\sa SetRefractionColor();
\return The RGB value of the refraction color.
*/
const Vector3& TRITONAPI GetRefractionColor() const;
/** Scales the intensity of reflections on the water (environment, planar, and light reflections combined.)
Default is 1.0. */
void TRITONAPI SetReflectionScale(float reflectionScale);
/** Retrieves any reflection scale set previously by SetReflectionScale(), or 1.0 otherwise. */
float TRITONAPI GetReflectionScale() const;
/** Sets the prominence of planar reflections on this ocean surface, if one was set using Triton::Environment::SetPlanarReflectionMap().
\param percent The percent by which planar reflections will be blended into the reflected color of the water (0 - 1.0).
*/
void TRITONAPI SetPlanarReflectionBlend(float blendPercent);
/** Retrieves the current blend percentage for planar reflections. \sa SetPlanarReflectionBlend(). */
float TRITONAPI GetPlanarReflectionBlend() const;
/** A helper function for using planar reflections with Triton. This will suggest useful matrices for flipping
your scene about the plane of the local water surface, and a texture matrix to transform world vectors into
texture coordinates in a reflection map. You may need to transpose and/or adjust these matrices for left handed
coordinates, depending on the conventions of your engine. The texture matrix returned will take the differences
between OpenGL and DirectX normalized device coordinates and texture coordinates into account, however.
\sa Triton::Environment::SetPlanarReflectionMap()
\param reflectionMatrix A matrix that will flip the scene about the local water plane, taking the current sea level
into account. If you multiply this matrix into your modelview matrix after your camera transforms, all objects will
be flipped about the water plane - making them suitable for rendering into a reflection texture map to later be
passed in to Triton::Environment::SetPlanarReflectionMap(). You will need to change the winding order used for back
face culling when this matrix is active, and you may also need to enable a user clipping plane to prevent geometry
that is normally underwater from rendering into your reflection texture.
\param textureMatrix A matrix to transform world vectors into texture coordinate space of the reflection map texture.
This matrix would be passed into Triton::Environment::SetPlanarReflectionMap(). This is equal to the product of
view * projection * NDCtoTexCoords, based on the view and projection matrices last passed to Environment::SetCameraMatrix()
and Environment::SetProjectionMatrix(). The matrix to transform normalized device coordinates to texture coordinates
will differ depending on whether an OpenGL or DirectX renderer is being used.
\return True if valid matrices were computed; will return false if the camera is below sea level, in which case you
probably don't want reflections anyhow.
*/
bool TRITONAPI ComputeReflectionMatrices(Matrix4& reflectionMatrix, Matrix3& textureMatrix, const Camera* camera = 0);
/** Retrieves the environment this ocean is attached to. */
const Environment * TRITONAPI GetEnvironment() const {
return environment;
}
/** Returns whether the current camera position (from Environment::SetCameraMatrix()) is above the simulated
water surface for this Ocean. */
virtual bool TRITONAPI IsCameraAboveWater(const Camera* camera = 0);
/** Applies a depth offset to the water, applied in the vertex program. This can be used to mitigate "z fighting" artifacts near
shorelines. By default, there is no depth offset. A value of 0.01 is generally effective.
\param offset The depth offset subtracted from the Z (depth) value in normalized coordinate space when rendering the ocean.
*/
void TRITONAPI SetDepthOffset(float offset);
/** Retrieves the depth offset (if any) previously set via Triton::Ocean::SetDepthOffset(), used to combat "z fighting" near coastlines. */
float TRITONAPI GetDepthOffset() const;
/** Sets the distance at which 3D wave displacements are dampened to prevent aliasing when moving the camera. */
void TRITONAPI SetDisplacementDampingDistance(double distance);
/** Retrieves the distance at which 3D wave displacements are dampened to prevent aliasing when moving the camera. */
double TRITONAPI GetDisplacementDampingDistance() const;
/** Turns the underwater crepuscular rays effect on or off. If the Triton.config setting underwater-god-rays-enabled is set to "no", this
will have no effect. Defaults to false.
*/
void TRITONAPI EnableGodRays(bool enable) {
enableGodRays = enable;
}
/** Returns whether the underwater crepuscular rays effect is enabled. */
bool TRITONAPI GodRaysEnabled() const {
return godRays != 0 && enableGodRays;
}
/** Fades out the underwater crepuscular rays effect by the specified amount (0 = no fading, 1 = completely faded). */
void TRITONAPI SetGodRaysFade(float fadeAmount);
/** Returns the god ray fading amount set in Ocean::FadeGodRays(). */
float TRITONAPI GetGodRaysFade() const;
/** Explicitly locks the mutex used to ensure thread safety between the draw, update, and height query methods. For example, if
you wish to conduct many calls to Ocean::GetHeight(), it is more efficient to enclose them with calls to Lock / Unlock and then
pass false for Ocean::GetHeight()'s threadSafety parameter. Make sure this call is balanced by a call to Triton::Unlock() under
every circumstance. */
void TRITONAPI Lock();
/** Explicitly locks the ocean's mutex previously locked by Ocean::Lock(). */
void TRITONAPI Unlock();
/** Set a quality setting (GOOD, BETTER, or BEST.) Higher quality will result in finer wave resolution, but at lower performance.
Default value is GOOD. Changing the quality setting requires deleting and re-initializing most of Triton's internal objects,
and so there will be a pause while this change is processed. */
void TRITONAPI SetQuality(OceanQuality quality);
/** Retrieve the current simulation quality setting, either set by Ocean::SetQuality() or the default value of GOOD. */
OceanQuality TRITONAPI GetQuality() const {
return quality;
}
/** Sets use of linear color space, in which the ocean color will be raised to the power of 2.2 to negate the effects of
gamma correction. Only set this if you know you are rendering in linear color space. */
void TRITONAPI SetLinearColorSpace(bool linearOn);
/** Gets whether linear color space rendering is enabled via SetLinearColorSpace(). */
bool TRITONAPI GetLinearColorSpace() const;
/** Sets a maximum wave period in the simulated wave spectra, irrespective of the wind conditions requested. */
void TRITONAPI SetMaximumWavePeriod(double maxPeriod);
/** Retrieves the maximum wave period enforced regardless of wind conditions requested. */
double TRITONAPI GetMaximumWavePeriod() const;
/** Tells Triton about the projected Z values at your near and far clipping planes.
May be used to dynamically switch between forward and reverse depth buffers,
for example. Defaults to the Triton.config settings for [opengl|directx]-[near|far]-clip */
void TRITONAPI SetClipDistances(double nearClip, double farClip);
/** Retrieves Triton's current assumptions about the projected Z values at your near
and far clipping planes. */
void TRITONAPI GetClipDistances(double& nearClip, double& farClip) const;
/** Explicitly overrides the H0 input array of wave amplitudes for given wavelengths
and directions, as described in Tessendorf's paper. This allows you to completely
override Triton's wave model with your own, but you really have to know what
you're doing. The size of this array must be of (N+1) * (M+1), where N and M
are given by the Triton.config settings fft-grid-size-x and fft-grid-size-y, and
both N and M are multiplied by 2 if BEST quality is selected for the ocean.
You can think of this as a 2D array that ranges from (-N/2) to (N/2) and from
(-M/2) to (M/2) with 0 in the middle. The direction from the center of the 2D
array represents the direction of each individual wave in a given array element.
The distance from the center represents the wavelength, normalized by the
maximum wavelength defined by fft-grid-size-x. Each array element contains a
complex number that represents both the amplitude and phase of the wave defined
by that element's wavelength and direction. You first need to convert the wave
amplitude into a Fourier amplitude by dividing the amplitude by two times the
square root of Pi. The real component of the complex number is given by the
Fourier amplitude times that cosine of the phase, and the imaginary component is
the Fourier amplitude times the sine of the phase.
Once you specify an overridden FFT input array, it will take effect until you either
submit a new one, or clear it out with Environment::ClearFFTInputArray() to return
to Triton's own model.
\param H0 A pointer to an array of Complex FFT inputs as described above. This
data will be copied internally and you may release this array when done.
\param size The number of Complex elements in the array provided.
\return True if the provided array is of the expected size and was accepted;
otherwise false.
*/
bool TRITONAPI OverrideFFTInputArray(const TritComplex *H0, unsigned int size);
/** Stops using an overridden FFT wave input array as defined in Environment::OverrideFFTInputArray. */
void TRITONAPI ClearFFTInputArray();
/** Retrieves the current FFT wave input array as described in Environment::OverrideFFTInputArray. */
const TritComplex* GetFFTInputArray(unsigned int& size);
/** Toggle rotor wash decals at run time. */
void TRITONAPI SetRotorWashUseDecals(bool useDecals);
bool TRITONAPI GetRotorWashUseDecals(void) const;
/** Change the water model at run time.
* Only works if the underlying water model is an fft water model
*/
void TRITONAPI SetWaterModel(WaterModelTypes waterModel);
/** Get the underlying water model. */
WaterModelTypes TRITONAPI GetWaterModel(void) const;
// Wrappers for interpreted languages require a publicly declared default constructor. You should always use Ocean::Create, however.
Ocean() {}
#ifndef SWIG
// Used internally
void RegisterWakeGenerator(WakeGenerator* wg);
void UnregisterWakeGenerator(WakeGenerator *wg);
void RegisterRotorWash(RotorWash *rw);
void UnregisterRotorWash(RotorWash *rw);
void RegisterTidalStreamWake(TidalStreamWake *tsw);
void UnregisterTidalStreamWake(TidalStreamWake *tsw);
void EnvironmentDeleted();
void NotifySwellsChanged();
void SetConfused(bool);
void UpdateHeightMap(void* context, const Camera* camera, TextureHandle heightMap, const Matrix4& heightMapMatrix);
GodRays *GetGodRays() const { return godRays; }
const TRITON_VECTOR(unsigned int)& GetUserShaders() const {return userShaders;}
ProjectedGrid* GetProjectedGrid() const {return grid;}
typedef void(*GETOCEANHEIGHTPROC)(const Vector3& point, Vector3& normal, float& height);
void TRITONAPI SetOceanHeightCB(GETOCEANHEIGHTPROC _oceanHeightCB) {
oceanHeightCB = _oceanHeightCB;
}
GETOCEANHEIGHTPROC TRITONAPI GetOceanHeightCB() const {
return oceanHeightCB;
}
protected:
Ocean(Environment *env, WaterModelTypes type, bool enableHeightTest, bool enableBreakingWaves, OceanQuality quality);
Ocean(Environment *env, WaterModelTypes type, bool enableHeightTest, bool enableBreakingWaves, OceanQuality quality, const TRITON_VECTOR(unsigned int)& userShaders);
virtual void Initialize(const Environment *env, WaterModelTypes type, bool enableHeightTest, bool enableBreakingWaves);
virtual bool CreateWaterSimulation();
void DestroyWaterSimulation();
void SetWaveHeading(const Camera* camera);
void DrawInternal(double time, bool depthWrites, bool drawWater, bool drawParticles, void* context, const Camera* camera, bool respectThreadSafe, bool respectAvoidStalls);
bool isGlobal, initialized, heightReadsEnabled, enableGodRays;
Environment *environment;
ProjectedGrid *grid;
WakeManager *wakeManager;
SprayManager *sprayManager;
DecalManager *decalManager;
GodRays *godRays;
float waveHeading;
bool sprayEnabled, enableKelvin;
double dampingDistance;
Mutex *mutex;
bool simulationUpdated;
WaterModelTypes waterModelType;
double lastUpdateTime;
const Camera* lastCamera;
double timeAdjustment;
TRITON_VECTOR(WakeGenerator *) wakeGenerators;
TRITON_VECTOR(RotorWash *) rotorWashes;
TRITON_VECTOR(TidalStreamWake *) tidalStreams;
TRITON_VECTOR(unsigned int) userShaders;
bool hasBreakingWaves, linearEnabled;
OceanQuality quality;
GETOCEANHEIGHTPROC oceanHeightCB;
WaterModelInitializationParams* watermodelparams;
double cameraMotionThreshold;
void createAndInitializeFallbackWaterModel(void);
#endif //SWIG
};
}
#pragma pack(pop)
#endif