From b814d180089b1e5415f89554e46de2edd978a592 Mon Sep 17 00:00:00 2001 From: Halldor Fannar Date: Thu, 9 Feb 2017 15:26:47 +0000 Subject: First publish of the SDK. --- README.md | 12 +- docs/Ansel_integration_guide.html | 924 +++++++++++++++++++++ docs/Ansel_integration_guide.md | 713 ++++++++++++++++ docs/Blur.jpg | Bin 0 -> 125918 bytes ...ameWorks Binary SDK EULA _ NVIDIA Developer.txt | 317 +++++++ docs/GhostingEverywhere.jpg | Bin 0 -> 214863 bytes docs/ImageAcne.jpg | Bin 0 -> 824568 bytes docs/ImageWithoutAcne.jpg | Bin 0 -> 228708 bytes docs/NvCameraConfiguration.exe_screen.png | Bin 0 -> 47096 bytes docs/ScreenSpaceReflections.jpg | Bin 0 -> 160061 bytes docs/ScreenSpaceReflectionsReduced.jpg | Bin 0 -> 154375 bytes docs/StreakyReflections.jpg | Bin 0 -> 160646 bytes include/AnselSDK.h | 33 + include/ansel/Camera.h | 63 ++ include/ansel/Configuration.h | 180 ++++ include/ansel/Defines.h | 39 + include/ansel/Hints.h | 67 ++ include/ansel/Session.h | 105 +++ include/ansel/Version.h | 52 ++ include/nv/Quat.h | 10 + include/nv/Vec3.h | 12 + .../AnselSDKDelayLoader.vcxproj | 228 +++++ .../AnselSDKDelayLoader.vcxproj.filters | 19 + samples/AnselSDKDelayLoader/source/DelayLoader.cpp | 281 +++++++ samples/AnselSDKDelayLoader/source/DelayLoader.h | 41 + 25 files changed, 3094 insertions(+), 2 deletions(-) create mode 100644 docs/Ansel_integration_guide.html create mode 100644 docs/Ansel_integration_guide.md create mode 100644 docs/Blur.jpg create mode 100644 docs/GameWorks Binary SDK EULA _ NVIDIA Developer.txt create mode 100644 docs/GhostingEverywhere.jpg create mode 100644 docs/ImageAcne.jpg create mode 100644 docs/ImageWithoutAcne.jpg create mode 100644 docs/NvCameraConfiguration.exe_screen.png create mode 100644 docs/ScreenSpaceReflections.jpg create mode 100644 docs/ScreenSpaceReflectionsReduced.jpg create mode 100644 docs/StreakyReflections.jpg create mode 100644 include/AnselSDK.h create mode 100644 include/ansel/Camera.h create mode 100644 include/ansel/Configuration.h create mode 100644 include/ansel/Defines.h create mode 100644 include/ansel/Hints.h create mode 100644 include/ansel/Session.h create mode 100644 include/ansel/Version.h create mode 100644 include/nv/Quat.h create mode 100644 include/nv/Vec3.h create mode 100644 samples/AnselSDKDelayLoader/AnselSDKDelayLoader.vcxproj create mode 100644 samples/AnselSDKDelayLoader/AnselSDKDelayLoader.vcxproj.filters create mode 100644 samples/AnselSDKDelayLoader/source/DelayLoader.cpp create mode 100644 samples/AnselSDKDelayLoader/source/DelayLoader.h diff --git a/README.md b/README.md index f63c168..18d2977 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ -# AnselSDK -This is where the SDK for NVIDIA Ansel is released to the public. +Ansel SDK +========= +* Version: 1.1.1027.6e9b4e3a +* Minimum driver version: 378.49 + +To use this version of the SDK with your application the NVIDIA display driver must be of the minimum driver version +listed above (or higher). On computers that have an older driver Ansel will not activate. + +Consult the [header files of the SDK](include) and the [integration guide](docs/Ansel_integration_guide.md) for detailed +documentation. diff --git a/docs/Ansel_integration_guide.html b/docs/Ansel_integration_guide.html new file mode 100644 index 0000000..05da426 --- /dev/null +++ b/docs/Ansel_integration_guide.html @@ -0,0 +1,924 @@ + + + + + Ansel_integration_guide.md - Grip + + + + + + +
+
+ + + +
+
+
+
+ +

+ + Ansel_integration_guide.md +

+ +
+

+ANSEL INTEGRATION GUIDE

+ +

+1. SETTING UP

+ +

+1.1 CODE, COMPILER, AND LINKER CONFIGURATION

+ +

The include folder in the Ansel SDK contains all the public header files you will need. A top-level include file, +AnselSDK.h, is provided for convenience so that you only need to include that one file in your project's code. If you +add the path to the Ansel SDK include folder to your project settings this is all you need to gain access to the +functionality of the SDK:

+ +
#include <AnselSDK.h>
+ +

Note that we do not offer Ansel SDK for static linking: this is intentional. The lib folder in the Ansel SDK contains +the import libraries for 32-bit and 64-bit architecture DLLs. Based on the targeted platform architecture you must link +in the corresponding import library.

+ +

If you wish to delay load the Ansel SDK, a sample project and source files are provided in the +samples folder. You can either link in the resulting static lib that this sample produces or simply include the source +files directly in your game. Regardless of which route you choose for delay loading you need to define +ANSEL_SDK_DELAYLOAD for the game and call the loadAnselSDKLibrary function that is implemented by the sample. +The Ansel SDK needs to be loaded via this function before any call is made to Ansel SDK functions (except the +ansel::isAnselAvailable function which can always be called - this function is covered in detail later in this +document). All other aspects of the Ansel SDK integration should remain the same and no special workflow is required +once the Ansel SDK has been loaded.

+ +

The redist folder in the Ansel SDK contains the DLLs for 32-bit and 64-bit architecture. These DLLs must be +redistributed with the game - if the game is only offered for 64-bit architecture then only 64-bit DLLs should be +redistributed (and similarly for 32-bit).

+ +

+1.2 MACHINE CONFIGURATION

+ +

In order to use Ansel you need

+ +
    +
  • Windows PC with Windows 7 (32-bit or 64-bit) or newer
  • +
  • GeForce GTX 600 series or newer
  • +
  • Ansel-ready display driver. In order to take advantage of all features of the SDK a driver of version 378.49 or higher +is required.
  • +
  • A game using Dx11 that has integrated the Ansel SDK
  • +
+ +
+

NOTE:

+ +
    +
  • Support for Dx12 is coming soon and options for OpenGL are being investigated.
  • +
  • We currently do not support Ansel for the following NVIDIA GPU / Display configurations + +
      +
    • Surround
    • +
    +
  • +
+
+ +

⚠️ Your game executable needs to be whitelisted by the driver for Ansel activation to succeed. If you do not +have a driver with the proper whitelisting you can force whitelisting to succeed for all executables with this command:

+ +
NvCameraEnable.exe whitelisting-everything
+
+ +

This utility is provided with the installation of an Ansel-ready display driver. You will find it at +NVIDIA Corporation/Ansel/Tools under Program Files. +The whitelisting setting will be persisted - until you perform a clean driver install or call +the command again with whitelisting-default option.

+ +

+1.3 GAME ENGINE CONFIGURATION

+ +

Ansel currently supports the following backbuffer formats:

+ + + + + + + + + + + + + + + + + + + + + + + + +
Supported formats
DXGI_FORMAT_R8G8B8A8_UNORM
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
DXGI_FORMAT_B8G8R8A8_UNORM
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
DXGI_FORMAT_R10G10B10A2_UNORM
+ +

Additionally, multisampling is supported for all the above formats. If your game is using a format that is not on the list +Ansel will produce images with zero for every pixel - i.e. black.

+ +

+2. INTEGRATING SDK WITH YOUR GAME

+ +

This Ansel SDK uses four major concepts: Configuration, Session, Camera, and optionally Hints. We will go through each of +them in turn and build up an example of game integration in the process.

+ +
+

NOTE: Please consult the header files in the Ansel SDK for reference style documentation.

+
+ +

+2.1 CONFIGURATION

+ +

As the first step in detecting whether a host computer can support Ansel (correct driver, Ansel enabled, +title whitelisted, etc) the following function should be called:

+ +
ANSEL_SDK_API bool isAnselAvailable();
+ +

This function can be called at any time (prior to calling any other function of Ansel) but it +should be called after the game has created its graphics device. If called prior to device creation it will always +return false. The function above is useful as the first step in determining if Ansel should be initialized for +this game session. If delay loading of the Ansel SDK is being used then a game could for instance choose to only load +the Ansel SDK library if the above function returned true. Please note that initialization of Ansel for this particular +game can still fail during the ansel::setConfiguration call (see below). This means that a game should only advertise + Ansel functionality if both ansel::isAnselAvailable returns true and ansel::setConfiguration succeeds.

+ +

During the initialization phase of the game the Ansel configuration should be specified. This is done via the +ansel::Configuration object. Please consult the header file, ansel/Configuration.h, for detailed documentation on +each field and default values for each. This is how configuration is typically performed:

+ +
#include <AnselSDK.h>
+...
+// during initialization phase of game:
+ansel::Configuration config;
+// Configure values that we want different from defaults:
+config.translationalSpeedInWorldUnitsPerSecond = 5.0f;
+config.right =   { -axis_left.x,   -axis_left.y,   -axis_left.z };
+config.up =      {  axis_up.x,      axis_up.y,      axis_up.z };
+config.forward = {  axis_forward.x, axis_forward.y, axis_forward.z };
+
+config.fovType = ansel::kVerticalFov;
+config.isCameraOffcenteredProjectionSupported = true;
+config.isCameraRotationSupported = true;
+config.isCameraTranslationSupported = true; 
+config.isCameraFovSupported = true;
+config.isFilterOutsideSessionAllowed = false; 
+
+config.gameWindowHandle = hWnd;
+config.titleNameUtf8 = u8"Best Game Ever";
+
+config.startSessionCallback = startAnselSessionCallback;
+config.stopSessionCallback = stopAnselSessionCallback;
+config.startCaptureCallback = startAnselCaptureCallback;
+config.stopCaptureCallback = stopAnselCaptureCallback;
+
+auto status = ansel::setConfiguration(config);
+if (status != ansel::kSetConfigurationSuccess)
+  // Report error, keep calm, and carry on
+ +
+

NOTE: Ansel cannot be activated by the player until the configuration has been successfully set. It is therefore advisable to perform the configuration soon after the AnselSDK DLL has been loaded. Also note that a failed setConfiguration call is not +catastrophic. It means that Ansel cannot by activated by the player so none of the callbacks or any other parts of the SDK will +come into use. The programmer is therefore not burdened with having to wrap Ansel SDK calls for the failure case. It is enough +to report it for debugging purposes. The setConfiguration call will never fail if the integeration has been performed correctly.

+
+ +

Let's go through this particular configuration in order.

+ +

Games used different units to represent size - it is therefore not possible in Ansel to have a uniform translational +speed that works for all games. This is why you will have to set the translationalSpeedInWorldUnitsPerSecond to a value +that feels right for your game. Move the camera around once Ansel mode has been activated to test your settings; test it +also with the accelerator key pressed (see Chapter 3 for Ansel controls)

+ +

Note that even though a game must specify how many meters (or fraction of a meter) are in a world unit +(see Configuration::metersInWorldUnit) this by itself is not enough to derive a default speed that works well for all +games. Some games have large worlds where travel is often performed in vehicles (or on mounts) while other games use +much smaller worlds and thus much lower travel speeds.

+ +

Games use different orientations and chirality (handed-ness) for their coordinate system and camera. The conversion between game +and Ansel's internal coordinate system and camera is handled by Ansel. This greatly simplifies +integration for game developers. You must specify the unit vectors for right, up, and forward directions that your default +oriented game camera uses as part of the configuration step. Once that is done all orientations exchanged between Ansel SDK and +the game will be in the game's coordinate system (see section 2.3 for more details). The right, up, and forward directions that +you provide must coincide with the default orientation of the game's camera. That is, if no rotation was applied to the +camera these are the values of its right, up, and forward axes.

+ +

Games will either use vertical or horizontal angle to specify the field of view. The default value in the Ansel +configuration is horizontal angle but if your game uses vertical angle you must specify ansel::kVerticalFov as the +fovType. This will free you from having to convert between the game's field of view and Ansel's internal field of view +(see section 2.3 for details).

+ +

Not all features of Ansel will necessarily be supported by a game integration. There are also cases where some features +of Ansel will be disabled under a particular game scenario. Here we will only discuss the general settings that reflect +the Ansel integration with the particular game engine; we will cover specific game scenarios in section 2.2.

+ +

In order to support high resolution capture, where screenshots are taken at resolutions higher than display resolution, +the game engine needs to support off center projection. In the Configuration object you specify if this feature is +supported by this particular game integration via the isCameraOffcenteredProjectionSupported field. Similarly, +support for allowing players to move, orient and zoom the camera is specified via the other Supported fields. We will +discuss in detail how support for these features is implemented in section 2.3.

+ +

The game must provide the window handle to its main window (the window that receives focus when the game is active - +this is the same window that receives mouse events). Ansel will automatically hide the Windows mouse cursor when +Ansel UI is enabled. Restoring the visbility of the Windows cursor cannot be done reliably by Ansel for all games. It is +therefore necessary to call Windows API ShowCursor if the game wants the mouse cursor to be visible after the Ansel UI is closed. +For completeness a game can call ShowCursor(false) to hide the mouse cursor in the start session callback (this is not +necessary) and ShowCursor(true) to restore it in the stop session callback (this may be necessary for your game - of +course depending on whether the cursor should be visible for the current game state).

+ +

Finally we have the session and capture callbacks. The capture callbacks are optional. Those should only be configured +if the game uses non-uniform screen based effects that cause issues in multipart shots. An example of an effect that +causes issues is vignette. Applying this effect to all the individual tiles of a highres capture or 360 capture will +produce poor results. The startCaptureCallback will be called when the multipart capture sequence starts and can +therefore be used to disable vignette. The startCaptureCallback passes a const reference to a CaptureConfiguration +object containing information about the capture about to be taken. The vignette can then be restored when stopCaptureCallback +is called. A game integration could of course chose to disable vignette when Ansel session is started but we recommend +against this since it would remove the vignette from regular screen shots (non-multipart shot). Note that all these +callbacks receive the value of the userPointer that is specified in the Configuration object.

+ +

Usually the version field in the ansel::Configuration structure is default initialized (if an object was created +using the default constructor and not aggregate initialization or copy from other object for instance) and doesn't need +to be set explicitly. In case an object is not created using the default constructor, the version field needs to be set to +ANSEL_SDK_VERSION defined in ansel/Version.h.

+ +

The session callbacks are mandatory, they are called when a player wants to begin an Ansel session or end a session. +Without these callbacks Ansel cannot be activated. We will discuss them in detail in the next section.

+ +
+

NOTE: All callbacks in Ansel will be triggered from calling D3D Present. They will therefore also happen on the same +thread that calls D3D Present.

+
+ +

The ansel::setConfiguration function returns its status. The possible return values are:

+ +
    enum SetConfigurationStatus
+    {
+        kSetConfigurationSuccess,                 // successfully initialized the Ansel SDK.
+        kSetConfigurationIncompatibleVersion,     // the version provided in the Configuration structure is
+                                                  // not the same as the one stored inside the SDK binary (header/binary mismatch).
+        kSetConfigurationIncorrectConfiguration,  // the Configuration structure supplied for the setConfiguration call is 
+                                                  // not consistent
+        kSetConfigurationSdkNotLoaded             // the Ansel SDK is delay loaded and setConfiguration is called before 
+                                                  // the SDK is actually loaded
+    };
+ +

The integration should only continue as normal (with regard to the Ansel functionality at least) when +kSetConfigurationSuccess is returned. +In case kSetConfigurationIncompatibleVersion is returned, most likely the Ansel SDK binary was obtained +without updating the headers, which also contain a version. Every update of the Ansel SDK requires a new build of a game. +In case kSetConfigurationIncorrectConfiguration is returned, on of the following fields could be set incorrectly:

+ +
    +
  • right, up, forward vectors do not form an orthogonal basis
  • +
  • startSessionCallback or stopSessionCallback is nullptr
  • +
  • rotational or translational speed multipliers are zero
  • +
  • fovType is neither horizontal, nor vertical
  • +
  • gameWindowHandle field is not set +In case kSetConfigurationSdkNotLoaded is returned, the reason is that the Ansel SDK is delay loaded and +setConfiguration is called before loading the library via loadAnselSDKLibrary (see code under samples folder).
  • +
+ +

+2.2 SESSION

+ +

The time period from when a player successfully starts Ansel and until Ansel is stopped is called a session. A session +is collaboratively started and operated between the game and Ansel. When a player requests a session start (for example +by pressing ALT+F2) Ansel will call the registered session start callback. It is however expected that Ansel cannot +always be activated. The game may for instance be on a loading screen or playing a movie sequence. The callback should +then immediately return with Ansel::kDisallowed return value.

+ +

During an Ansel session the game:

+ +
    +
  • Must stop drawing UI and HUD elements on the screen, including mouse cursor
  • +
  • Must call ansel::updateCamera on every frame (see section 2.3 for details)
  • +
  • Should pause rendering time (i.e. no movement should be visible in the world)
  • +
  • Should not act on any input from mouse and keyboard and must not act on any input from gamepads
  • +
+ +

The function signatures of the session related callbacks are listed below.

+ +
enum StartSessionStatus
+{
+    kDisallowed = 0,
+    kAllowed
+};
+
+typedef StartSessionStatus(*StartSessionCallback)(SessionConfiguration& settings, void* userPointer);
+
+typedef void(*StopSessionCallback)(void* userPointer);
+ +

As you will notice the start callback receives an additional SessionConfiguration object. This object must reflect the configuration of the currently activated session if Ansel::kAllowed is returned from the callback. Let's take a look at this configuration object:

+ +
struct SessionConfiguration
+{
+    // User can move the camera during session
+      bool isTranslationAllowed;
+    // Camera can be rotated during session
+    bool isRotationAllowed;
+    // FoV can be modified during session
+    bool isFovChangeAllowed;
+    // Game is paused during session
+    bool isPauseAllowed;
+    // Game allows highres capture during session
+    bool isHighresAllowed;
+    // Game allows 360 capture during session
+    bool is360MonoAllowed;
+    // Game allows 360 stereo capture during session
+    bool is360StereoAllowed;
+      // Default constructor not included here
+};
+ +

As you can see each session has fine grained control over what features of Ansel are offered to the player. This is to +support different contexts that the game may be in - where some features of Ansel may not be desired. For instance, +let's say that a game uses in-engine movie sequences. Ansel could certainly be used to take regular and highres +screenshots during those sequences. However, the game developers may wish to prohibit any player controlled camera +movement or 360 captures during those sequences since they could expose geometry that was never built because the +sequences have been carefully orchestrated. This is what such a callback could look like:

+ +
ansel::StartSessionStatus startAnselSessionCallback(ansel::SessionConfiguration& conf, 
+                           void* userPointer)
+{
+    if (isGameLoading || isGameInMenuScreens)
+        return ansel::kDisallowed;
+
+    if (isGameCutScenePlaying)
+    {
+        conf.isTranslationAllowed = false;
+        conf.isRotationAllowed = false;
+        conf.isFovChangeAllowed = false;
+        conf.is360MonoAllowed = false;
+        conf.is360StereoAllowed = false;
+    }
+
+     g_isAnselSessionActive = true;
+
+      return ansel::kAllowed;
+}
+ +
+

NOTE: The final feature set presented in the Ansel UI is always a combination of the global configuration +specified via the ansel::Configuration object and the particular session configuration specified via the +ansel::SessionConfiguration object. For instance, if off-center projection is not supported by the +integration and this is marked as such in the global configuration then the isHighresAllowed setting will +have no effect for an Ansel session because the feature is simply not supported by the integration.

+ +

Similarly, if isRotationAllowed is set to false for the session then no form of 360 capture will be +possible and hence the is360MonoAllowed and is360StereoAllowed will have no effect. In the sample code above we +still set them but this is done for clarity and completeness.

+
+ +

In a session where rendering time cannot be paused this can be communicated with the isPauseAllowed setting. This could +for instance be the case in a game that offers multiplayer game modes. That being said, some multiplayer game engines +still allow rendering time to be frozen - this just means that the state of the world will have advanced when the Ansel +session ends. The stitcher developed for Ansel does not currently support feature detection or other methods used to +handle temporal inconsistencies. This means that multipart shots (highres and 360) are not supported during sessions +when pause is disallowed.

+ +

The stop session callback is called when the player requests to end the session (for instance by pressing ALT+F2). This +function is only called if the previous call to start session returned ansel::kAllowed. The matching function to what +we implemented above would look like this:

+ +
void stopAnselSessionCallback(void* userPointer)
+{
+    g_isAnselSessionActive = false;
+}
+ +

A game can trigger a session start or stop (which leads to the above mentioned callbacks being eventually called). +This is done using the following interface from Session.h:

+ +
ANSEL_SDK_API void startSession();
+ANSEL_SDK_API void stopSession();
+ +

This can be used to enable activation of Ansel UI via gamepad for instance. A game can use its existing gamepad handling +to call ansel::startSession() if for instance left-stick is pressed (and a session is not already active). Similarly, +ansel::stopSession() should be called when the same action is performed and session is active. The game is expected +to track whether a session is active via the start/stop session callbacks that were outlined earlier in this section. +Other means of Ansel activation could of course be employed (different keyboard shortcut, etc) and the game could call +start/stopSession accordingly.

+ +

+2.3 CAMERA

+ +

The camera object acts as the communication channel between Ansel and the game. The concepts described earlier are +either used for one-off configuration or rare events. Once an Ansel session has been started the game needs to call +Ansel on every frame to update the camera. It's helpful to first look at the Camera interface:

+ +
struct Camera
+{
+    nv::Vec3 position;
+    nv::Quat rotation;
+    float fov;
+    float projectionOffsetX, projectionOffsetY;
+};
+
+ANSEL_SDK_API void updateCamera(Camera& camera);
+ +

As noted before the header file contains documentation for each field. Here it suffices to say that the values are all +in the game's coordinate system, since this has been established via the ansel::setConfiguration call +(see section 2.1). The field of view, fov, is in degrees and in the format specified during the previously mentioned +call. The final two values are used to specify the off-center projection amount. Let's illustrate how this all works +with sample code following the earlier session callbacks we had created:

+ +
if (g_isAnselSessionActive)
+{
+  if (!was_ansel_in_control)
+  {
+    store_original_camera_settings();
+    was_ansel_in_control = true;
+  }
+  ansel::Camera cam;
+  cam.fov = get_game_fov_vertical_degrees();
+  cam.position = { game_cam_position.x, game_cam_position.y,
+                   game_cam_position.z };
+  cam.rotation = { game_cam_orientation.x,
+                   game_cam_orientation.y,
+                   game_cam_orientation.z,
+                   game_cam_orientation.w };
+
+  ansel::updateCamera(cam);
+  // This is where a game would typically perform collision detection
+  // and adjust the values requested by player in cam.position 
+
+  game_cam_position.x = cam.position.x;
+  game_cam_position.y = cam.position.y;
+  game_cam_position.z = cam.position.z;
+
+  game_cam_orientation.x = cam.rotation.x;
+  game_cam_orientation.y = cam.rotation.y;
+  game_cam_orientation.z = cam.rotation.z;
+  game_cam_orientation.w = cam.rotation.w;
+
+  set_game_fov_vertical_degrees(cam.fov);
+
+  // modify projection matrices by the offset amounts -
+  // we will explore this in detail separately  
+  offset_game_projection_matrices(cam.projectionOffsetX, cam.projectionOffsetY);
+
+  return;
+}
+else
+{
+  if (was_ansel_in_control)
+  {
+    restore_original_camera_settings();
+    was_ansel_in_control = false;
+  }
+}
+ +

The sample above is a full implementation of Ansel support, in the sense that it supports camera translation, camera +rotation, changing of field of view, and offset projection. Most rendering engines employ a view matrix; the camera +is most often just a game side concept. Fortunately the view matrix is just the inverse of the camera matrix so it's easy +to obtain. Remember that the camera matrix is established by transforming the default camera by the camera rotation. +Since some code bases use matrices rather than quaternions for rotations we provide a couple of utility +functions in the Camera interface:

+ +
ANSEL_SDK_API void quaternionToRotationMatrixVectors(const nv::Quat& q, 
+                                                     nv::Vec3& right, nv::Vec3& up, nv::Vec3& forward);
+
+ANSEL_SDK_API void rotationMatrixVectorsToQuaternion(const nv::Vec3& right, const nv::Vec3& up, const nv::Vec3& forward, 
+                                                     nv::Quat& q);
+ +

The former one can be used to convert the ansel::Camera::rotation to a matrix that can then be used to transform +the basis vectors of the game's default oriented camera to establish the camera matrix. The latter can be used to +convert the game's camera rotation matrix to a quaternion that can be passed into ansel::Camera::rotation prior to +calling ansel::updateCamera.

+ +

Even though the sample above is a full implementation of Ansel support it does however not employ any collision detection +or other constraints on the camera movement. This is unrealistic since most games will at least want to limit the range the +camera can travel. These limitations will always be specific to the game in question and collision is best +handled by the game using the systems that are already in place. We do therefore not elaborate on this piece here. It +should still be noted that Ansel is stateless when it comes to position so the game can adjust the position (based on +collision response or constraints) any way it sees fit. The new position will always be communicated to Ansel on the +next frame, via ansel::updateCamera.

+ +

Another aspect that is not covered in the sample code above is the handling of projection offset. We will explore that +aspect in more detail here.

+ +

The projectionOffsetX and projectionOffsetY members of the ansel::Camera specify the amount that the projection +matrix needs to be offset by. These values are normalized coordinates applied directly to the projection matrix, they +should not need any scaling. These values are only used by Super Resolution captures - for all other capture types +they will be zero. Expanding on the sample code above:

+ +
void offset_game_projection_matrices(float offsetX, float offsetY)
+{
+  // In this simple example we only need to modify the projection matrix associated with the game camera. 
+  // If the game is doing clever things like optimizing reflections or shadows based on projection matrix
+  // then those code paths need to take a non-zero projection offset into account.
+
+  // For nostalgia effect this game is using an old classic:
+  D3DXMATRIX projection;
+  D3DXMatrixPerspectiveFovRH(&projection, g_fov_radians, g_aspect, g_z_near, g_z_far)
+
+  // Apply the offsets directly to the finished product (values are already normalized):
+  projection._31 += offsetX;
+  projection._32 += offsetY;
+
+  // Update the games projection matrix:
+  g_projection_matrix = projection;
+}
+ +

+2.4 HINTS

+ +

To perform Raw capture (to EXR format) Ansel tries to use certain heuristics to detect which of the game buffers +contains HDR pixel data. These heuristics won't work for all games. For instance, they won't work for games that use +deferred contexts with multithreaded rendering. For those scenarios the hinting API can be used (see ansel/Hints.h).

+ +

Below we will outline how the hinting API is used to make capture work under these circumstances. +If game developers do not want to use the hinting API to make raw capture work the isRawAllowed setting in the +ansel::SessionConfiguration should be set to false during the startSession callback. This will disable the 'Raw' + option in the Ansel UI.

+ +
namespace ansel
+{
+    // Call this right before setting HDR render target active
+    ANSEL_SDK_API void markHdrBufferBind(uint64_t threadId = 0xFFFFFFFFFFFFFFFFull);
+    // Call this right after the last draw call into the HDR render target
+    ANSEL_SDK_API void markHdrBufferFinished(uint64_t threadId = 0xFFFFFFFFFFFFFFFFull, AnselHintsCopyMode copyMode = kAnselHintsCopyOnPresent);
+}
+
+ +

To identify the HDR buffer for Ansel call markHdrBufferBind before binding the buffer to the graphics pipeline. In case the buffer contents is not overwritten before calling Present +(or glSwapBuffers()) it is fine to not call markHdrBufferFinished. In case the same buffer is reused for other +purposes and at the time the Present (or glSwapBuffers) gets called its content does not represent the framebuffer +calling markHdrBufferFinished at the moment where the buffer is not used anymore but before it is unbound from the graphics +pipeline is neccessary. Both functions have threadId argument, which is an optional argument allowing Ansel to match the thread calling +a hint and a particular graphics API call that some other game thread might perform. The default value of 0xFFFFFFFFFFFFFFFFull means that +no such matching should happen. The special value of 0 means that Ansel SDK is going to match thread ids automatically. Any other +value means a specific thread id known at integration side. markHdrBufferFinished also allows setting the copyMode, which is an optional +argument specifying if HDR buffer is going to be reused or used in a fashion that is not compatible with capturing it at Present +(or analogous function, since this is graphics API dependent) call. The default value is kAnselHintsCopyOnPresent, which means the buffer +contents will remain in tact until Present call. In case copyMode is set to kAnselHintsCopyImmediately, HDR buffer will be copied upon +the next call to the graphics API that Ansel hooks.

+ +

+3. TAKING PICTURES WITH ANSEL

+ +

+3.1 ACTIVATING AND DEACTIVATING ANSEL

+ +

Players can start/stop Ansel session by pressing ALT+F2. Other ways of activation are possible if the game has used +the ansel::startSession and ansel::stopSession functions in the Ansel SDK to implement other triggers +(see section 2.2)

+ +

+3.2 MOVING THE CAMERA

+ +

The camera can be moved via keys WASD and XZ for up/down. The camera can also be moved with the left stick on a gamepad +and trigger buttons for up/down. Movement can be accelerated by holding SHIFT on keyboard or depressing right stick on +gamepad.

+ +

+3.3 ROTATING THE CAMERA

+ +

The yaw and pitch of the camera is directly controlled by mouse or right stick on gamepad. The roll of the camera is +adjusted via the user interface Roll slider but can also be controlled directly via shoulder buttons on gamepad.

+ +

+3.4 APPLYING A FILTER

+ +

A number of filters can be selected via the Filter slider. Some filters, like 'Custom' have additional settings that +can be used to adjust the filter even further.

+ +

+3.5 TAKING A PICTURE

+ +

Ansel offers the following capture types (selected via the Capture type slider):

+ +
    +
  • Screenshot
  • +
  • Highres
  • +
  • 360
  • +
  • Stereo
  • +
  • 360 Stereo
  • +
+ +

Not all of these capture types may be available since it depends on the game integration and the current session (see +sections 2.1 and 2.2). Once a type has been chosen the picture is taken by pressing Snap button. Some pictures may take +significant time to produce, especially highres shots of large dimensions. If the game uses streaming the streaming +performance may be affected when shots involving many parts are being stitched together.

+ +
+

NOTE:* Not all filters are valid with multipart Capture types (360 and Highres). You may therefore see filters (or +aspects of a filter) removed in the final picture.

+
+ +

+4. TROUBLESHOOTING AND DEBUGGING COMMON PROBLEMS

+ +

In this section we collected commonly occurring problems we've seen while integrating Ansel with games. This section can +hopefully help you resolve a problem or two. +It is generally useful to be able to inspect the individual shot tiles that are captured when generating pictures that +require multiple shots. Locate the NvCameraConfiguration.exe utility. It can be found inside +Program Files\NVIDIA Corporation\Ansel\Tools.

+ +

Run the utility. A screen similar to this one should appear:

+ +

NvCameraConfiguration utility

+ +

Check the 'Keep Intermediate Shots' option so that you can inspect the individual tiles. You can also pick a different +location to store the tiles by changing the 'Temp Directory for Intermediate Shots'.

+ +

Notice the 'Log level' setting. By default this is set to 'Disabled', which means that no logs are produced. If you set +this to for instance 'Info' then all log messages with severity Info and higher will be emitted to a log file. Log files +are stored in the current users profile directory, inside an 'ansel' folder. The path is %USERPROFILE%\ansel. Each +log file is named after the associated executable and includes a timestamp. Please note that multiple log files can be +produced by the same game during one session since each device starts a separate Ansel logging session. That being said +only one device (and therefore log file) will be associated with the presentable surface and will thus contain the most +helpful information.

+ +

+4.1 ANSEL CANNOT BE ACTIVATED

+ +

There are a number of configuration issues that can result in Ansel not activating for your game when you press the +activation keys (ALT+F2). The following list is helpful in debugging the issue: +1. Verify that Ansel is enabled for the machine. You can do this by running the NvCameraEnable.exe utility with no +arguments (this tool was introduced in section 1.2). It will return 1 if Ansel is enabled, 0 otherwise. You can +change this setting by issuing NvCameraEnable.exe on or using the GUI tool NvCameraConfiguration.exe that was +introduced in the beginning of this chapter. +2. If the game executable is not whitelisted for Ansel (by the installed driver) you can disable whitelisting checks as +outlined in section 1.2. +3. Verify that the hardware and software requirements from sections 1.2 and 1.3 are met by the machine and game. +4. If you are running on a Hybrid/Optimus computer that has both a integrated GPU and a discreet NVIDIA GPU, make sure +the game is running on the NVIDIA GPU. Use the NVIDIA Control Panel to verify/configure this setting for the game. +5. Verify that Ansel is trying to start by setting a breakpoint on the startSessionCallback. +6. Depending on which phase is blocking Ansel activation, logging can be helpful. See the beginning of this chapter on +how to utilize logging.

+ +

+4.2 ARTEFACTS IN MULTIPART SHOTS

+ +

This is where we cover the most common errors we've seen while capturing multipart shots in games.

+ +

+4.2.1 Image tiles suffer from "acne"

+ +

This is probably best described with images. Here is a tile exhibiting the problem:

+ +

Image acne

+ +

Note the "acne" to the left of the tree, caused by temporal anti-aliasing. This can be fixed in two different ways. One +method is to use the captureSettleLatency field in the configuration object. This field specifies how many frames Ansel +should wait when taking multipart shots for the frame to settle - i.e. for any temporal effects to have settled. In this +specific case (where the image is taken from) it takes one frame so the value should be 1. This is what the image looks +like with that setting:

+ +

Image without acne

+ +

Another way to solve this problem is to harness the startCapture/stopCapture callbacks to disable temporal AA. This +effectively disables the temporal AA feature during the multipart capture sequence. +Which solution should you use? Well, it depends. You need to subjectively evaluate how much the temporal AA enhances +image quality vs the cost of waiting for the frame to settle. At a settleLatency of 1 the cost is rather small and thus +weighs in favor of using that solution.

+ +

+4.2.2 Ghosting everywhere in final picture

+ +

Usually it looks something like this:

+ +

Ghosting everywhere

+ +

Most often this is the result of incorrect field of view being submitted to Ansel - or error made on conversion or usage +of value coming back from Ansel. It is recommended that you match the field of view type between game and Ansel to avoid +any conversion mistakes. See section 2.1 on how you can configure Ansel to use the game's field of view.

+ +

+4.2.3 Screen space reflections fade out with increased Highres capture resolution

+ +

Below is a regular screenshot taken with Ansel:

+ +

Screen space reflections

+ +

If we now select capture type Highres with a large enough multiplier we get this picture (scaled down in resolution to +fit this document):

+ +

Screen space reflections reduced

+ +

There is unfortunately no workaround for this problem, it is a limitation of the capture method used.

+ +

+4.2.4 It's all a blur

+ +

Motion blur needs to be disabled during multipart capture. Otherwise results like this can be produced when taking 360 +picture:

+ +

Blurry capture

+ +

+4.2.5 Streaky reflections

+ +

When enabling highres capture for your game you may witness results similar to this:

+ +

Streaky reflections in capture

+ +

The reason may be that the projection offset and reduced field of view employed by the highres capture method is not +being accounted for in the game's reflection code path.

+ +

+4.3 THE VIEW OF THE WORLD "POPS" WHEN ENTERING AND EXITING ANSEL MODE

+ +

This is typically due to incorrect field of view being passed on the first frame or due to a screen space effect being +disabled when Ansel mode is activated. For the latter it is preferred to deactivate troublesome effects only during +multipart captures (via the capture callback).

+ +

+4.4 GAME MOUSE CURSOR IS NOT VISIBLE AFTER RETURNING TO GAME FROM ANSEL

+ +

The visible state of the mouse cursor needs to be restored by calling Windows API SetCursor(true) when the Ansel +session has ended (after ansel::Configuration::stopSessionCallback is triggered).

+ +

+4.5 DOUBLE MOUSE CURSORS

+ +

Strictly speaking UI and HUD elements must not be rendered when game is in Ansel mode and this includes any cursors. We +have however experienced the situation where the game renders a mouse cursor on top of its window when it regains focus. +If the game is in Ansel mode this will result in two moving mouse cursors - a very confusing experience indeed. As +mentioned the game shouldn't be rendering a mouse cursor when Ansel is active. That being said we have a mechanism to +prevent this from happening - this mechanism is enabled if the game passes its window handle during configuration, in +the Configuration::gameWindowHandle field.

+ +

+4.6 CAMERA ROTATION OR MOVEMENT IS INCORRECT

+ +

Incorrect rotation is best observed with a gamepad - i.e. pushing the joystick left doesn't rotate the view towards the +left or pushing the joystick up doesn't rotate the view up. Incorrect movement can be verified with either keyboard or +gamepad.

+ +

This problem is usually rooted in incorrect axes provided for right, up, and down directions in the +ansel::Configuration struct. See section 2.1.

+ +

+4.7 CAMERA ROTATION OR MOVEMENT IS TOO SLOW / TOO FAST

+ +

The speed for rotation is set via the rotationalSpeedInDegreesPerSecond field during configuration. The default value +is 45 degrees/second. The speed for movement is set via the translationalSpeedInWorldUnitsPerSecond field during +configuration. The default value is 1 world unit/second.

+ +

+4.8 ALL ANSEL CAPTURES PRODUCE BLACK IMAGES

+ +

This is usually caused by an unsupported backbuffer format. Please consult section 1.3 for a list of supported formats.

+ +

+4.9 ALL ANSEL CAPTURES ARE NAMED AFTER THE GAME EXECUTABLE

+ +

This happens because the game does not have a GeForce profile (yet) and a setting for titleNameUtf8 was not specified +when ansel::setConfiguration was called. It is best to provide a name for the title via titleNameUtf8 since this +will work regardless of whether the driver being used has a GeForce profile for the game.

+ +

+4.9 RAW CAPTURE FAILS

+ +

By default Ansel uses heuristics to try to identify the raw HDR buffer. For some games these heuristics won't work. +Section 2.4 contains the information on how to address this.

+ +

+APPENDIX A

+ +

+Notice

+ +

The information provided in this specification is believed to be accurate and reliable as of the date provided. However, +NVIDIA Corporation ("NVIDIA") does not give any representations or warranties, expressed or implied, as to the accuracy or completeness of such information. NVIDIA shall have no liability for the consequences or use of such information or for any infringement of patents or other rights of third parties that may result from its use. This publication supersedes and replaces all other specifications for the product that may have been previously supplied. +NVIDIA reserves the right to make corrections, modifications, enhancements, improvements, and other changes to this specification, at any time and/or to discontinue any product or service without notice. Customer should obtain the latest relevant specification before placing orders and should verify that such information is current and complete. +NVIDIA products are sold subject to the NVIDIA standard terms and conditions of sale supplied at the time of order acknowledgement, unless otherwise agreed in an individual sales agreement signed by authorized representatives of NVIDIA and customer. NVIDIA hereby expressly objects to applying any customer general terms and conditions with regard to the purchase of the NVIDIA product referenced in this specification. +NVIDIA products are not designed, authorized or warranted to be suitable for use in medical, military, aircraft, space or life support equipment, nor in applications where failure or malfunction of the NVIDIA product can reasonably be expected to result in personal injury, death or property or environmental damage. NVIDIA accepts no liability for inclusion and/or use of NVIDIA products in such equipment or applications and therefore such inclusion and/or use is at customer's own risk. +NVIDIA makes no representation or warranty that products based on these specifications will be suitable for any specified use without further testing or modification. Testing of all parameters of each product is not necessarily performed by NVIDIA. It is customer's sole responsibility to ensure the product is suitable and fit for the application planned by customer and to do the necessary testing for the application in order to avoid a default of the application or the product. Weaknesses in customer's product designs may affect the quality and reliability of the NVIDIA product and may result in additional or different conditions and/or requirements beyond those contained in this specification. NVIDIA does not accept any liability related to any default, damage, costs or problem which may be based on or attributable to: (i) the use of the NVIDIA product in any manner that is contrary to this specification, or (ii) customer product designs. +No license, either expressed or implied, is granted under any NVIDIA patent right, copyright, or other NVIDIA intellectual property right under this specification. Information published by NVIDIA regarding third-party products or services does not constitute a license from NVIDIA to use such products or services or a warranty or endorsement thereof. Use of such information may require a license from a third party under the patents or other intellectual property rights of the third party, or a license from NVIDIA under the patents or other intellectual property rights of NVIDIA. Reproduction of information in this specification is permissible only if reproduction is approved by NVIDIA in writing, is reproduced without alteration, and is accompanied by all associated conditions, limitations, and notices. +ALL NVIDIA DESIGN SPECIFICATIONS, REFERENCE BOARDS, FILES, DRAWINGS, DIAGNOSTICS, LISTS, AND OTHER DOCUMENTS (TOGETHER AND SEPARATELY, "MATERIALS") ARE BEING PROVIDED "AS IS." NVIDIA MAKES NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. Notwithstanding any damages that customer might incur for any reason whatsoever, NVIDIA's aggregate and cumulative liability towards customer for the products described herein shall be limited in accordance with the NVIDIA terms and conditions of sale for the product.

+ +

VESA DisplayPort +DisplayPort and DisplayPort Compliance Logo, DisplayPort Compliance Logo for Dual-mode Sources, and DisplayPort Compliance Logo for Active Cables are trademarks owned by the Video Electronics Standards Association in the United States and other countries.

+ +

HDMI +HDMI, the HDMI logo, and High-Definition Multimedia Interface are trademarks or registered trademarks of HDMI Licensing LLC.

+ +

ROVI Compliance Statement +NVIDIA Products that support Rovi Corporation's Revision 7.1.L1 Anti-Copy Process (ACP) encoding technology can only be sold or distributed to buyers with a valid and existing authorization from ROVI to purchase and incorporate the device into buyer's products. +This device is protected by U.S. patent numbers 6,516,132; 5,583,936; 6,836,549; 7,050,698; and 7,492,896 and other intellectual property rights. The use of ROVI Corporation's copy protection technology in the device must be authorized by ROVI Corporation and is intended for home and other limited pay-per-view uses only, unless otherwise authorized in writing by ROVI Corporation. Reverse engineering or disassembly is prohibited.

+ +

OpenCL +OpenCL is a trademark of Apple Inc. used under license to the Khronos Group Inc.

+ +

Trademarks +NVIDIA and the NVIDIA logo are trademarks and/or registered trademarks of NVIDIA Corporation in the U.S. and other countries. Other company and product names may be trademarks of the respective companies with which they are associated.

+ +

Copyright +(c) 2016 NVIDIA Corporation. All rights reserved.

+ +

www.nvidia.com

+ +
+
+
+
+
+ + + +
+
 
+
+ + \ No newline at end of file diff --git a/docs/Ansel_integration_guide.md b/docs/Ansel_integration_guide.md new file mode 100644 index 0000000..b7b2590 --- /dev/null +++ b/docs/Ansel_integration_guide.md @@ -0,0 +1,713 @@ +ANSEL INTEGRATION GUIDE +======================= + + +1. SETTING UP +------------- +### 1.1 CODE, COMPILER, AND LINKER CONFIGURATION +The include folder in the Ansel SDK contains all the public header files you will need. A top-level include file, +AnselSDK.h, is provided for convenience so that you only need to include that one file in your project's code. If you +add the path to the Ansel SDK include folder to your project settings this is all you need to gain access to the +functionality of the SDK: + +```cpp +#include +``` +Note that we do not offer Ansel SDK for static linking: this is intentional. The lib folder in the Ansel SDK contains +the import libraries for 32-bit and 64-bit architecture DLLs. Based on the targeted platform architecture you must link +in the corresponding import library. + +If you wish to delay load the Ansel SDK, a sample project and source files are provided in the +samples folder. You can either link in the resulting static lib that this sample produces or simply include the source +files directly in your game. Regardless of which route you choose for delay loading you need to define +`ANSEL_SDK_DELAYLOAD` for the game and call the `loadAnselSDKLibrary` function that is implemented by the sample. +The Ansel SDK needs to be loaded via this function before any call is made to Ansel SDK functions (except the +`ansel::isAnselAvailable` function which can always be called - this function is covered in detail later in this +document). All other aspects of the Ansel SDK integration should remain the same and no special workflow is required +once the Ansel SDK has been loaded. + +The redist folder in the Ansel SDK contains the DLLs for 32-bit and 64-bit architecture. These DLLs must be +redistributed with the game - if the game is only offered for 64-bit architecture then only 64-bit DLLs should be +redistributed (and similarly for 32-bit). + +### 1.2 MACHINE CONFIGURATION +In order to use Ansel you need + +* Windows PC with Windows 7 (32-bit or 64-bit) or newer +* GeForce GTX 600 series or newer +* Ansel-ready display driver. In order to take advantage of all features of the SDK a driver of version 378.49 or higher + is required. +* A game using Dx11 that has integrated the Ansel SDK + +> **NOTE:** +> * Support for Dx12 is coming soon and options for OpenGL are being investigated. +> * We currently do not support Ansel for the following NVIDIA GPU / Display configurations +> * Surround + +:warning: Your game executable needs to be whitelisted by the driver for Ansel activation to succeed. If you do not +have a driver with the proper whitelisting you can force whitelisting to succeed for all executables with this command: + +```ms-dos +NvCameraEnable.exe whitelisting-everything +``` + +This utility is provided with the installation of an Ansel-ready display driver. You will find it at +NVIDIA Corporation/Ansel/Tools under Program Files. +The whitelisting setting will be persisted - until you perform a clean driver install or call +the command again with whitelisting-default option. + +### 1.3 GAME ENGINE CONFIGURATION +Ansel currently supports the following backbuffer formats: + +Supported formats | +--------------------------------| +DXGI_FORMAT_R8G8B8A8_UNORM | +DXGI_FORMAT_R8G8B8A8_UNORM_SRGB | +DXGI_FORMAT_B8G8R8A8_UNORM | +DXGI_FORMAT_B8G8R8A8_UNORM_SRGB | +DXGI_FORMAT_R10G10B10A2_UNORM | + +Additionally, multisampling is supported for all the above formats. If your game is using a format that is not on the list +Ansel will produce images with zero for every pixel - i.e. black. + +2. INTEGRATING SDK WITH YOUR GAME +--------------------------------- +This Ansel SDK uses four major concepts: Configuration, Session, Camera, and optionally Hints. We will go through each of +them in turn and build up an example of game integration in the process. + +> **NOTE:** Please consult the header files in the Ansel SDK for reference style documentation. + +### 2.1 CONFIGURATION +As the first step in detecting whether a host computer can support Ansel (correct driver, Ansel enabled, +title whitelisted, etc) the following function should be called: + +```cpp +ANSEL_SDK_API bool isAnselAvailable(); +``` + +This function can be called at any time (prior to calling any other function of Ansel) but it +should be called after the game has created its graphics device. If called prior to device creation it will always +return false. The function above is useful as the first step in determining if Ansel should be initialized for +this game session. If delay loading of the Ansel SDK is being used then a game could for instance choose to only load +the Ansel SDK library if the above function returned true. Please note that initialization of Ansel for this particular +game can still fail during the `ansel::setConfiguration` call (see below). This means that a game should only advertise + Ansel functionality if both `ansel::isAnselAvailable` returns true and `ansel::setConfiguration` succeeds. + +During the initialization phase of the game the Ansel configuration should be specified. This is done via the +`ansel::Configuration` object. Please consult the header file, ansel/Configuration.h, for detailed documentation on +each field and default values for each. This is how configuration is typically performed: + +```cpp +#include +... +// during initialization phase of game: +ansel::Configuration config; +// Configure values that we want different from defaults: +config.translationalSpeedInWorldUnitsPerSecond = 5.0f; +config.right = { -axis_left.x, -axis_left.y, -axis_left.z }; +config.up = { axis_up.x, axis_up.y, axis_up.z }; +config.forward = { axis_forward.x, axis_forward.y, axis_forward.z }; + +config.fovType = ansel::kVerticalFov; +config.isCameraOffcenteredProjectionSupported = true; +config.isCameraRotationSupported = true; +config.isCameraTranslationSupported = true; +config.isCameraFovSupported = true; +config.isFilterOutsideSessionAllowed = false; + +config.gameWindowHandle = hWnd; +config.titleNameUtf8 = u8"Best Game Ever"; + +config.startSessionCallback = startAnselSessionCallback; +config.stopSessionCallback = stopAnselSessionCallback; +config.startCaptureCallback = startAnselCaptureCallback; +config.stopCaptureCallback = stopAnselCaptureCallback; + +auto status = ansel::setConfiguration(config); +if (status != ansel::kSetConfigurationSuccess) + // Report error, keep calm, and carry on +``` + +> **NOTE:** Ansel cannot be activated by the player until the configuration has been successfully set. It is therefore advisable to perform the configuration soon after the AnselSDK DLL has been loaded. Also note that a failed `setConfiguration` call is not +catastrophic. It means that Ansel cannot by activated by the player so none of the callbacks or any other parts of the SDK will +come into use. The programmer is therefore not burdened with having to wrap Ansel SDK calls for the failure case. It is enough +to report it for debugging purposes. The `setConfiguration` call will never fail if the integeration has been performed correctly. + +Let's go through this particular configuration in order. + +Games used different units to represent size - it is therefore not possible in Ansel to have a uniform translational +speed that works for all games. This is why you will have to set the translationalSpeedInWorldUnitsPerSecond to a value +that feels right for your game. Move the camera around once Ansel mode has been activated to test your settings; test it +also with the accelerator key pressed (see Chapter 3 for Ansel controls) + +Note that even though a game must specify how many meters (or fraction of a meter) are in a world unit +(see Configuration::metersInWorldUnit) this by itself is not enough to derive a default speed that works well for all +games. Some games have large worlds where travel is often performed in vehicles (or on mounts) while other games use +much smaller worlds and thus much lower travel speeds. + +Games use different orientations and chirality (handed-ness) for their coordinate system and camera. The conversion between game +and Ansel's internal coordinate system and camera is handled by Ansel. This greatly simplifies +integration for game developers. You must specify the unit vectors for right, up, and forward directions that your default +oriented game camera uses as part of the configuration step. Once that is done all orientations exchanged between Ansel SDK and +the game will be in the game's coordinate system (see section 2.3 for more details). The right, up, and forward directions that +you provide must coincide with the default orientation of the game's camera. That is, if no rotation was applied to the +camera these are the values of its right, up, and forward axes. + +Games will either use vertical or horizontal angle to specify the field of view. The default value in the Ansel +configuration is horizontal angle but if your game uses vertical angle you must specify ansel::kVerticalFov as the +fovType. This will free you from having to convert between the game's field of view and Ansel's internal field of view +(see section 2.3 for details). + +Not all features of Ansel will necessarily be supported by a game integration. There are also cases where some features +of Ansel will be disabled under a particular game scenario. Here we will only discuss the general settings that reflect +the Ansel integration with the particular game engine; we will cover specific game scenarios in section 2.2. + +In order to support high resolution capture, where screenshots are taken at resolutions higher than display resolution, +the game engine needs to support off center projection. In the Configuration object you specify if this feature is +supported by this particular game integration via the isCameraOffcenteredProjectionSupported field. Similarly, +support for allowing players to move, orient and zoom the camera is specified via the other Supported fields. We will +discuss in detail how support for these features is implemented in section 2.3. + +The game must provide the window handle to its main window (the window that receives focus when the game is active - +this is the same window that receives mouse events). Ansel will automatically hide the Windows mouse cursor when +Ansel UI is enabled. Restoring the visbility of the Windows cursor cannot be done reliably by Ansel for all games. It is +therefore necessary to call Windows API `ShowCursor` if the game wants the mouse cursor to be visible after the Ansel UI is closed. +For completeness a game can call `ShowCursor(false)` to hide the mouse cursor in the start session callback (this is not +necessary) and `ShowCursor(true)` to restore it in the stop session callback (this may be necessary for your game - of +course depending on whether the cursor should be visible for the current game state). + +Finally we have the session and capture callbacks. The capture callbacks are optional. Those should only be configured +if the game uses non-uniform screen based effects that cause issues in multipart shots. An example of an effect that +causes issues is vignette. Applying this effect to all the individual tiles of a highres capture or 360 capture will +produce poor results. The startCaptureCallback will be called when the multipart capture sequence starts and can +therefore be used to disable vignette. The startCaptureCallback passes a const reference to a CaptureConfiguration +object containing information about the capture about to be taken. The vignette can then be restored when stopCaptureCallback +is called. A game integration could of course chose to disable vignette when Ansel session is started but we recommend +against this since it would remove the vignette from regular screen shots (non-multipart shot). Note that all these +callbacks receive the value of the userPointer that is specified in the Configuration object. + +Usually the version field in the ansel::Configuration structure is default initialized (if an object was created +using the default constructor and not aggregate initialization or copy from other object for instance) and doesn't need +to be set explicitly. In case an object is not created using the default constructor, the version field needs to be set to +ANSEL_SDK_VERSION defined in ansel/Version.h. + +The session callbacks are mandatory, they are called when a player wants to begin an Ansel session or end a session. +Without these callbacks Ansel cannot be activated. We will discuss them in detail in the next section. + +> **NOTE:** All callbacks in Ansel will be triggered from calling D3D Present. They will therefore also happen on the same +thread that calls D3D Present. + +The ansel::setConfiguration function returns its status. The possible return values are: +```cpp + enum SetConfigurationStatus + { + kSetConfigurationSuccess, // successfully initialized the Ansel SDK. + kSetConfigurationIncompatibleVersion, // the version provided in the Configuration structure is + // not the same as the one stored inside the SDK binary (header/binary mismatch). + kSetConfigurationIncorrectConfiguration, // the Configuration structure supplied for the setConfiguration call is + // not consistent + kSetConfigurationSdkNotLoaded // the Ansel SDK is delay loaded and setConfiguration is called before + // the SDK is actually loaded + }; +``` + +The integration should only continue as normal (with regard to the Ansel functionality at least) when +kSetConfigurationSuccess is returned. +In case kSetConfigurationIncompatibleVersion is returned, most likely the Ansel SDK binary was obtained +without updating the headers, which also contain a version. Every update of the Ansel SDK requires a new build of a game. +In case kSetConfigurationIncorrectConfiguration is returned, on of the following fields could be set incorrectly: +* right, up, forward vectors do not form an orthogonal basis +* startSessionCallback or stopSessionCallback is nullptr +* rotational or translational speed multipliers are zero +* fovType is neither horizontal, nor vertical +* gameWindowHandle field is not set +In case `kSetConfigurationSdkNotLoaded` is returned, the reason is that the Ansel SDK is delay loaded and +setConfiguration is called before loading the library via `loadAnselSDKLibrary` (see code under samples folder). + +### 2.2 SESSION +The time period from when a player successfully starts Ansel and until Ansel is stopped is called a session. A session +is collaboratively started and operated between the game and Ansel. When a player requests a session start (for example +by pressing ALT+F2) Ansel will call the registered session start callback. It is however expected that Ansel cannot +always be activated. The game may for instance be on a loading screen or playing a movie sequence. The callback should +then immediately return with Ansel::kDisallowed return value. + +During an Ansel session the game: + +* Must stop drawing UI and HUD elements on the screen, including mouse cursor +* Must call ansel::updateCamera on every frame (see section 2.3 for details) +* Should pause rendering time (i.e. no movement should be visible in the world) +* Should not act on any input from mouse and keyboard and must not act on any input from gamepads + +The function signatures of the session related callbacks are listed below. + +```cpp +enum StartSessionStatus +{ + kDisallowed = 0, + kAllowed +}; + +typedef StartSessionStatus(*StartSessionCallback)(SessionConfiguration& settings, void* userPointer); + +typedef void(*StopSessionCallback)(void* userPointer); +``` + +As you will notice the start callback receives an additional SessionConfiguration object. This object must reflect the configuration of the currently activated session if Ansel::kAllowed is returned from the callback. Let's take a look at this configuration object: + +```cpp +struct SessionConfiguration +{ + // User can move the camera during session + bool isTranslationAllowed; + // Camera can be rotated during session + bool isRotationAllowed; + // FoV can be modified during session + bool isFovChangeAllowed; + // Game is paused during session + bool isPauseAllowed; + // Game allows highres capture during session + bool isHighresAllowed; + // Game allows 360 capture during session + bool is360MonoAllowed; + // Game allows 360 stereo capture during session + bool is360StereoAllowed; + // Default constructor not included here +}; +``` + +As you can see each session has fine grained control over what features of Ansel are offered to the player. This is to +support different contexts that the game may be in - where some features of Ansel may not be desired. For instance, +let's say that a game uses in-engine movie sequences. Ansel could certainly be used to take regular and highres +screenshots during those sequences. However, the game developers may wish to prohibit any player controlled camera +movement or 360 captures during those sequences since they could expose geometry that was never built because the +sequences have been carefully orchestrated. This is what such a callback could look like: + +```cpp +ansel::StartSessionStatus startAnselSessionCallback(ansel::SessionConfiguration& conf, + void* userPointer) +{ + if (isGameLoading || isGameInMenuScreens) + return ansel::kDisallowed; + + if (isGameCutScenePlaying) + { + conf.isTranslationAllowed = false; + conf.isRotationAllowed = false; + conf.isFovChangeAllowed = false; + conf.is360MonoAllowed = false; + conf.is360StereoAllowed = false; + } + + g_isAnselSessionActive = true; + + return ansel::kAllowed; +} +``` + +> **NOTE:** The final feature set presented in the Ansel UI is always a combination of the global configuration +specified via the ansel::Configuration object and the particular session configuration specified via the +ansel::SessionConfiguration object. For instance, if off-center projection is not supported by the +integration and this is marked as such in the global configuration then the isHighresAllowed setting will +have no effect for an Ansel session because the feature is simply not supported by the integration. + +> Similarly, if `isRotationAllowed` is set to false for the session then no form of 360 capture will be +possible and hence the `is360MonoAllowed` and `is360StereoAllowed` will have no effect. In the sample code above we +still set them but this is done for clarity and completeness. + +In a session where rendering time cannot be paused this can be communicated with the isPauseAllowed setting. This could +for instance be the case in a game that offers multiplayer game modes. That being said, some multiplayer game engines +still allow rendering time to be frozen - this just means that the state of the world will have advanced when the Ansel +session ends. The stitcher developed for Ansel does not currently support feature detection or other methods used to +handle temporal inconsistencies. This means that multipart shots (highres and 360) are not supported during sessions +when pause is disallowed. + +The stop session callback is called when the player requests to end the session (for instance by pressing ALT+F2). This +function is only called if the previous call to start session returned `ansel::kAllowed`. The matching function to what +we implemented above would look like this: + +```cpp +void stopAnselSessionCallback(void* userPointer) +{ + g_isAnselSessionActive = false; +} +``` + +A game can trigger a session start or stop (which leads to the above mentioned callbacks being eventually called). +This is done using the following interface from Session.h: + +```cpp +ANSEL_SDK_API void startSession(); +ANSEL_SDK_API void stopSession(); +``` + +This can be used to enable activation of Ansel UI via gamepad for instance. A game can use its existing gamepad handling +to call `ansel::startSession()` if for instance left-stick is pressed (and a session is not already active). Similarly, +`ansel::stopSession()` should be called when the same action is performed and session is active. The game is expected +to track whether a session is active via the start/stop session callbacks that were outlined earlier in this section. +Other means of Ansel activation could of course be employed (different keyboard shortcut, etc) and the game could call +start/stopSession accordingly. + +### 2.3 CAMERA +The camera object acts as the communication channel between Ansel and the game. The concepts described earlier are +either used for one-off configuration or rare events. Once an Ansel session has been started the game needs to call +Ansel on every frame to update the camera. It's helpful to first look at the Camera interface: + +```cpp +struct Camera +{ + nv::Vec3 position; + nv::Quat rotation; + float fov; + float projectionOffsetX, projectionOffsetY; +}; + +ANSEL_SDK_API void updateCamera(Camera& camera); +``` + +As noted before the header file contains documentation for each field. Here it suffices to say that the values are all +in the game's coordinate system, since this has been established via the `ansel::setConfiguration` call +(see section 2.1). The field of view, fov, is in degrees and in the format specified during the previously mentioned +call. The final two values are used to specify the off-center projection amount. Let's illustrate how this all works +with sample code following the earlier session callbacks we had created: + +```cpp +if (g_isAnselSessionActive) +{ + if (!was_ansel_in_control) + { + store_original_camera_settings(); + was_ansel_in_control = true; + } + ansel::Camera cam; + cam.fov = get_game_fov_vertical_degrees(); + cam.position = { game_cam_position.x, game_cam_position.y, + game_cam_position.z }; + cam.rotation = { game_cam_orientation.x, + game_cam_orientation.y, + game_cam_orientation.z, + game_cam_orientation.w }; + + ansel::updateCamera(cam); + // This is where a game would typically perform collision detection + // and adjust the values requested by player in cam.position + + game_cam_position.x = cam.position.x; + game_cam_position.y = cam.position.y; + game_cam_position.z = cam.position.z; + + game_cam_orientation.x = cam.rotation.x; + game_cam_orientation.y = cam.rotation.y; + game_cam_orientation.z = cam.rotation.z; + game_cam_orientation.w = cam.rotation.w; + + set_game_fov_vertical_degrees(cam.fov); + + // modify projection matrices by the offset amounts - + // we will explore this in detail separately + offset_game_projection_matrices(cam.projectionOffsetX, cam.projectionOffsetY); + + return; +} +else +{ + if (was_ansel_in_control) + { + restore_original_camera_settings(); + was_ansel_in_control = false; + } +} +``` + +The sample above is a full implementation of Ansel support, in the sense that it supports camera translation, camera +rotation, changing of field of view, and offset projection. Most rendering engines employ a view matrix; the camera +is most often just a game side concept. Fortunately the view matrix is just the inverse of the camera matrix so it's easy +to obtain. Remember that the camera matrix is established by transforming the default camera by the camera rotation. +Since some code bases use matrices rather than quaternions for rotations we provide a couple of utility +functions in the Camera interface: + +```cpp +ANSEL_SDK_API void quaternionToRotationMatrixVectors(const nv::Quat& q, + nv::Vec3& right, nv::Vec3& up, nv::Vec3& forward); + +ANSEL_SDK_API void rotationMatrixVectorsToQuaternion(const nv::Vec3& right, const nv::Vec3& up, const nv::Vec3& forward, + nv::Quat& q); +``` + +The former one can be used to convert the `ansel::Camera::rotation` to a matrix that can then be used to transform +the basis vectors of the game's default oriented camera to establish the camera matrix. The latter can be used to +convert the game's camera rotation matrix to a quaternion that can be passed into `ansel::Camera::rotation` prior to +calling `ansel::updateCamera`. + +Even though the sample above is a full implementation of Ansel support it does however not employ any collision detection +or other constraints on the camera movement. This is unrealistic since most games will at least want to limit the range the +camera can travel. These limitations will always be specific to the game in question and collision is best +handled by the game using the systems that are already in place. We do therefore not elaborate on this piece here. It +should still be noted that Ansel is stateless when it comes to position so the game can adjust the position (based on +collision response or constraints) any way it sees fit. The new position will always be communicated to Ansel on the +next frame, via `ansel::updateCamera`. + +Another aspect that is not covered in the sample code above is the handling of projection offset. We will explore that +aspect in more detail here. + +The `projectionOffsetX` and `projectionOffsetY` members of the `ansel::Camera` specify the amount that the projection +matrix needs to be offset by. These values are normalized coordinates applied directly to the projection matrix, they +should not need any scaling. These values are only used by Super Resolution captures - for all other capture types +they will be zero. Expanding on the sample code above: + +```cpp +void offset_game_projection_matrices(float offsetX, float offsetY) +{ + // In this simple example we only need to modify the projection matrix associated with the game camera. + // If the game is doing clever things like optimizing reflections or shadows based on projection matrix + // then those code paths need to take a non-zero projection offset into account. + + // For nostalgia effect this game is using an old classic: + D3DXMATRIX projection; + D3DXMatrixPerspectiveFovRH(&projection, g_fov_radians, g_aspect, g_z_near, g_z_far) + + // Apply the offsets directly to the finished product (values are already normalized): + projection._31 += offsetX; + projection._32 += offsetY; + + // Update the games projection matrix: + g_projection_matrix = projection; +} +``` + +### 2.4 HINTS +To perform Raw capture (to EXR format) Ansel tries to use certain heuristics to detect which of the game buffers +contains HDR pixel data. These heuristics won't work for all games. For instance, they won't work for games that use +deferred contexts with multithreaded rendering. For those scenarios the hinting API can be used (see ansel/Hints.h). + +Below we will outline how the hinting API is used to make capture work under these circumstances. +If game developers do not want to use the hinting API to make raw capture work the `isRawAllowed` setting in the +`ansel::SessionConfiguration` should be set to false during the startSession callback. This will disable the 'Raw' + option in the Ansel UI. +``` +namespace ansel +{ + // Call this right before setting HDR render target active + ANSEL_SDK_API void markHdrBufferBind(uint64_t threadId = 0xFFFFFFFFFFFFFFFFull); + // Call this right after the last draw call into the HDR render target + ANSEL_SDK_API void markHdrBufferFinished(uint64_t threadId = 0xFFFFFFFFFFFFFFFFull, AnselHintsCopyMode copyMode = kAnselHintsCopyOnPresent); +} +``` + +To identify the HDR buffer for Ansel call ```markHdrBufferBind``` before binding the buffer to the graphics pipeline. In case the buffer contents is not overwritten before calling ```Present``` +(or ```glSwapBuffers()```) it is fine to not call ```markHdrBufferFinished```. In case the same buffer is reused for other +purposes and at the time the ```Present``` (or ```glSwapBuffers```) gets called its content does not represent the framebuffer +calling ```markHdrBufferFinished``` at the moment where the buffer is not used anymore but before it is unbound from the graphics +pipeline is neccessary. Both functions have threadId argument, which is an optional argument allowing Ansel to match the thread calling +a hint and a particular graphics API call that some other game thread might perform. The default value of 0xFFFFFFFFFFFFFFFFull means that +no such matching should happen. The special value of 0 means that Ansel SDK is going to match thread ids automatically. Any other +value means a specific thread id known at integration side. markHdrBufferFinished also allows setting the copyMode, which is an optional +argument specifying if HDR buffer is going to be reused or used in a fashion that is not compatible with capturing it at Present +(or analogous function, since this is graphics API dependent) call. The default value is kAnselHintsCopyOnPresent, which means the buffer +contents will remain in tact until Present call. In case copyMode is set to kAnselHintsCopyImmediately, HDR buffer will be copied upon +the next call to the graphics API that Ansel hooks. + +3. TAKING PICTURES WITH ANSEL +----------------------------- +### 3.1 ACTIVATING AND DEACTIVATING ANSEL +Players can start/stop Ansel session by pressing ALT+F2. Other ways of activation are possible if the game has used +the `ansel::startSession` and `ansel::stopSession` functions in the Ansel SDK to implement other triggers +(see section 2.2) + +### 3.2 MOVING THE CAMERA +The camera can be moved via keys WASD and XZ for up/down. The camera can also be moved with the left stick on a gamepad +and trigger buttons for up/down. Movement can be accelerated by holding SHIFT on keyboard or depressing right stick on +gamepad. +### 3.3 ROTATING THE CAMERA +The yaw and pitch of the camera is directly controlled by mouse or right stick on gamepad. The roll of the camera is +adjusted via the user interface Roll slider but can also be controlled directly via shoulder buttons on gamepad. +### 3.4 APPLYING A FILTER +A number of filters can be selected via the Filter slider. Some filters, like 'Custom' have additional settings that +can be used to adjust the filter even further. +### 3.5 TAKING A PICTURE +Ansel offers the following capture types (selected via the Capture type slider): +* Screenshot +* Highres +* 360 +* Stereo +* 360 Stereo + +Not all of these capture types may be available since it depends on the game integration and the current session (see +sections 2.1 and 2.2). Once a type has been chosen the picture is taken by pressing Snap button. Some pictures may take +significant time to produce, especially highres shots of large dimensions. If the game uses streaming the streaming +performance may be affected when shots involving many parts are being stitched together. + +> **NOTE:*** Not all filters are valid with multipart Capture types (360 and Highres). You may therefore see filters (or +aspects of a filter) removed in the final picture. + + +4. TROUBLESHOOTING AND DEBUGGING COMMON PROBLEMS +------------------------------------------------ +In this section we collected commonly occurring problems we've seen while integrating Ansel with games. This section can +hopefully help you resolve a problem or two. +It is generally useful to be able to inspect the individual shot tiles that are captured when generating pictures that +require multiple shots. Locate the `NvCameraConfiguration.exe` utility. It can be found inside +Program Files\NVIDIA Corporation\Ansel\Tools. + +Run the utility. A screen similar to this one should appear: + +![NvCameraConfiguration utility](NvCameraConfiguration.exe_screen.png) + +Check the 'Keep Intermediate Shots' option so that you can inspect the individual tiles. You can also pick a different +location to store the tiles by changing the 'Temp Directory for Intermediate Shots'. + +Notice the 'Log level' setting. By default this is set to 'Disabled', which means that no logs are produced. If you set +this to for instance 'Info' then all log messages with severity Info and higher will be emitted to a log file. Log files +are stored in the current users profile directory, inside an 'ansel' folder. The path is `%USERPROFILE%\ansel`. Each +log file is named after the associated executable and includes a timestamp. Please note that multiple log files can be +produced by the same game during one session since each device starts a separate Ansel logging session. That being said +only one device (and therefore log file) will be associated with the presentable surface and will thus contain the most +helpful information. + +### 4.1 ANSEL CANNOT BE ACTIVATED +There are a number of configuration issues that can result in Ansel not activating for your game when you press the +activation keys (ALT+F2). The following list is helpful in debugging the issue: +1. Verify that Ansel is enabled for the machine. You can do this by running the `NvCameraEnable.exe` utility with no +arguments (this tool was introduced in section 1.2). It will return `1` if Ansel is enabled, `0` otherwise. You can +change this setting by issuing `NvCameraEnable.exe on` or using the GUI tool `NvCameraConfiguration.exe` that was +introduced in the beginning of this chapter. +2. If the game executable is not whitelisted for Ansel (by the installed driver) you can disable whitelisting checks as +outlined in section 1.2. +3. Verify that the hardware and software requirements from sections 1.2 and 1.3 are met by the machine and game. +4. If you are running on a Hybrid/Optimus computer that has both a integrated GPU and a discreet NVIDIA GPU, make sure +the game is running on the NVIDIA GPU. Use the NVIDIA Control Panel to verify/configure this setting for the game. +5. Verify that Ansel is trying to start by setting a breakpoint on the startSessionCallback. +6. Depending on which phase is blocking Ansel activation, logging can be helpful. See the beginning of this chapter on +how to utilize logging. + +### 4.2 ARTEFACTS IN MULTIPART SHOTS +This is where we cover the most common errors we've seen while capturing multipart shots in games. +#### 4.2.1 Image tiles suffer from "acne" +This is probably best described with images. Here is a tile exhibiting the problem: + +![Image acne](ImageAcne.jpg) + +Note the "acne" to the left of the tree, caused by temporal anti-aliasing. This can be fixed in two different ways. One +method is to use the captureSettleLatency field in the configuration object. This field specifies how many frames Ansel +should wait when taking multipart shots for the frame to settle - i.e. for any temporal effects to have settled. In this +specific case (where the image is taken from) it takes one frame so the value should be 1. This is what the image looks +like with that setting: + +![Image without acne](ImageWithoutAcne.jpg) + +Another way to solve this problem is to harness the startCapture/stopCapture callbacks to disable temporal AA. This +effectively disables the temporal AA feature during the multipart capture sequence. +Which solution should you use? Well, it depends. You need to subjectively evaluate how much the temporal AA enhances +image quality vs the cost of waiting for the frame to settle. At a settleLatency of 1 the cost is rather small and thus +weighs in favor of using that solution. + +#### 4.2.2 Ghosting everywhere in final picture +Usually it looks something like this: + +![Ghosting everywhere](GhostingEverywhere.jpg) + +Most often this is the result of incorrect field of view being submitted to Ansel - or error made on conversion or usage +of value coming back from Ansel. It is recommended that you match the field of view type between game and Ansel to avoid +any conversion mistakes. See section 2.1 on how you can configure Ansel to use the game's field of view. +#### 4.2.3 Screen space reflections fade out with increased Highres capture resolution +Below is a regular screenshot taken with Ansel: + +![Screen space reflections](ScreenSpaceReflections.jpg) + +If we now select capture type Highres with a large enough multiplier we get this picture (scaled down in resolution to +fit this document): + +![Screen space reflections reduced](ScreenSpaceReflectionsReduced.jpg) + +There is unfortunately no workaround for this problem, it is a limitation of the capture method used. +#### 4.2.4 It's all a blur +Motion blur needs to be disabled during multipart capture. Otherwise results like this can be produced when taking 360 +picture: + +![Blurry capture](Blur.jpg) + +#### 4.2.5 Streaky reflections +When enabling highres capture for your game you may witness results similar to this: + +![Streaky reflections in capture](StreakyReflections.jpg) + +The reason may be that the projection offset and reduced field of view employed by the highres capture method is not +being accounted for in the game's reflection code path. + +### 4.3 THE VIEW OF THE WORLD "POPS" WHEN ENTERING AND EXITING ANSEL MODE +This is typically due to incorrect field of view being passed on the first frame or due to a screen space effect being +disabled when Ansel mode is activated. For the latter it is preferred to deactivate troublesome effects only during +multipart captures (via the capture callback). + +### 4.4 GAME MOUSE CURSOR IS NOT VISIBLE AFTER RETURNING TO GAME FROM ANSEL +The visible state of the mouse cursor needs to be restored by calling Windows API `SetCursor(true)` when the Ansel +session has ended (after `ansel::Configuration::stopSessionCallback` is triggered). + +### 4.5 DOUBLE MOUSE CURSORS +Strictly speaking UI and HUD elements must not be rendered when game is in Ansel mode and this includes any cursors. We +have however experienced the situation where the game renders a mouse cursor on top of its window when it regains focus. +If the game is in Ansel mode this will result in two moving mouse cursors - a very confusing experience indeed. As +mentioned the game shouldn't be rendering a mouse cursor when Ansel is active. That being said we have a mechanism to +prevent this from happening - this mechanism is enabled if the game passes its window handle during configuration, in +the Configuration::gameWindowHandle field. + +### 4.6 CAMERA ROTATION OR MOVEMENT IS INCORRECT +Incorrect rotation is best observed with a gamepad - i.e. pushing the joystick left doesn't rotate the view towards the +left or pushing the joystick up doesn't rotate the view up. Incorrect movement can be verified with either keyboard or +gamepad. + +This problem is usually rooted in incorrect axes provided for right, up, and down directions in the +`ansel::Configuration` struct. See section 2.1. + +### 4.7 CAMERA ROTATION OR MOVEMENT IS TOO SLOW / TOO FAST +The speed for rotation is set via the `rotationalSpeedInDegreesPerSecond` field during configuration. The default value +is 45 degrees/second. The speed for movement is set via the `translationalSpeedInWorldUnitsPerSecond` field during +configuration. The default value is 1 world unit/second. + +### 4.8 ALL ANSEL CAPTURES PRODUCE BLACK IMAGES +This is usually caused by an unsupported backbuffer format. Please consult section 1.3 for a list of supported formats. + +### 4.9 ALL ANSEL CAPTURES ARE NAMED AFTER THE GAME EXECUTABLE +This happens because the game does not have a GeForce profile (yet) and a setting for `titleNameUtf8` was not specified +when `ansel::setConfiguration` was called. It is best to provide a name for the title via `titleNameUtf8` since this +will work regardless of whether the driver being used has a GeForce profile for the game. + +### 4.9 RAW CAPTURE FAILS +By default Ansel uses heuristics to try to identify the raw HDR buffer. For some games these heuristics won't work. +Section 2.4 contains the information on how to address this. + +APPENDIX A +---------- + +### Notice + +The information provided in this specification is believed to be accurate and reliable as of the date provided. However, +NVIDIA Corporation ("NVIDIA") does not give any representations or warranties, expressed or implied, as to the accuracy or completeness of such information. NVIDIA shall have no liability for the consequences or use of such information or for any infringement of patents or other rights of third parties that may result from its use. This publication supersedes and replaces all other specifications for the product that may have been previously supplied. +NVIDIA reserves the right to make corrections, modifications, enhancements, improvements, and other changes to this specification, at any time and/or to discontinue any product or service without notice. Customer should obtain the latest relevant specification before placing orders and should verify that such information is current and complete. +NVIDIA products are sold subject to the NVIDIA standard terms and conditions of sale supplied at the time of order acknowledgement, unless otherwise agreed in an individual sales agreement signed by authorized representatives of NVIDIA and customer. NVIDIA hereby expressly objects to applying any customer general terms and conditions with regard to the purchase of the NVIDIA product referenced in this specification. +NVIDIA products are not designed, authorized or warranted to be suitable for use in medical, military, aircraft, space or life support equipment, nor in applications where failure or malfunction of the NVIDIA product can reasonably be expected to result in personal injury, death or property or environmental damage. NVIDIA accepts no liability for inclusion and/or use of NVIDIA products in such equipment or applications and therefore such inclusion and/or use is at customer's own risk. +NVIDIA makes no representation or warranty that products based on these specifications will be suitable for any specified use without further testing or modification. Testing of all parameters of each product is not necessarily performed by NVIDIA. It is customer's sole responsibility to ensure the product is suitable and fit for the application planned by customer and to do the necessary testing for the application in order to avoid a default of the application or the product. Weaknesses in customer's product designs may affect the quality and reliability of the NVIDIA product and may result in additional or different conditions and/or requirements beyond those contained in this specification. NVIDIA does not accept any liability related to any default, damage, costs or problem which may be based on or attributable to: (i) the use of the NVIDIA product in any manner that is contrary to this specification, or (ii) customer product designs. +No license, either expressed or implied, is granted under any NVIDIA patent right, copyright, or other NVIDIA intellectual property right under this specification. Information published by NVIDIA regarding third-party products or services does not constitute a license from NVIDIA to use such products or services or a warranty or endorsement thereof. Use of such information may require a license from a third party under the patents or other intellectual property rights of the third party, or a license from NVIDIA under the patents or other intellectual property rights of NVIDIA. Reproduction of information in this specification is permissible only if reproduction is approved by NVIDIA in writing, is reproduced without alteration, and is accompanied by all associated conditions, limitations, and notices. +ALL NVIDIA DESIGN SPECIFICATIONS, REFERENCE BOARDS, FILES, DRAWINGS, DIAGNOSTICS, LISTS, AND OTHER DOCUMENTS (TOGETHER AND SEPARATELY, "MATERIALS") ARE BEING PROVIDED "AS IS." NVIDIA MAKES NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. Notwithstanding any damages that customer might incur for any reason whatsoever, NVIDIA's aggregate and cumulative liability towards customer for the products described herein shall be limited in accordance with the NVIDIA terms and conditions of sale for the product. + +VESA DisplayPort +DisplayPort and DisplayPort Compliance Logo, DisplayPort Compliance Logo for Dual-mode Sources, and DisplayPort Compliance Logo for Active Cables are trademarks owned by the Video Electronics Standards Association in the United States and other countries. + +HDMI +HDMI, the HDMI logo, and High-Definition Multimedia Interface are trademarks or registered trademarks of HDMI Licensing LLC. + +ROVI Compliance Statement +NVIDIA Products that support Rovi Corporation's Revision 7.1.L1 Anti-Copy Process (ACP) encoding technology can only be sold or distributed to buyers with a valid and existing authorization from ROVI to purchase and incorporate the device into buyer's products. +This device is protected by U.S. patent numbers 6,516,132; 5,583,936; 6,836,549; 7,050,698; and 7,492,896 and other intellectual property rights. The use of ROVI Corporation's copy protection technology in the device must be authorized by ROVI Corporation and is intended for home and other limited pay-per-view uses only, unless otherwise authorized in writing by ROVI Corporation. Reverse engineering or disassembly is prohibited. + +OpenCL +OpenCL is a trademark of Apple Inc. used under license to the Khronos Group Inc. + +Trademarks +NVIDIA and the NVIDIA logo are trademarks and/or registered trademarks of NVIDIA Corporation in the U.S. and other countries. Other company and product names may be trademarks of the respective companies with which they are associated. + +Copyright +(c) 2016 NVIDIA Corporation. All rights reserved. + + +www.nvidia.com + diff --git a/docs/Blur.jpg b/docs/Blur.jpg new file mode 100644 index 0000000..bcfcaff Binary files /dev/null and b/docs/Blur.jpg differ diff --git a/docs/GameWorks Binary SDK EULA _ NVIDIA Developer.txt b/docs/GameWorks Binary SDK EULA _ NVIDIA Developer.txt new file mode 100644 index 0000000..080634f --- /dev/null +++ b/docs/GameWorks Binary SDK EULA _ NVIDIA Developer.txt @@ -0,0 +1,317 @@ + + GameWorks Binary SDK EULA + +*NVIDIA CORPORATION +NVIDIA GAMEWORKS BINARY SDK END USER LICENSE AGREEMENT* + +NVIDIA Corporation ("NVIDIA") is willing to license the NVIDIA GameWorks +Binary SDK associated with this download and the accompanying +documentation, installation routines and support files, sample art files +and assets, and supporting utilities (collectively, the "NVIDIA +GameWorks SDK") to you only on the condition that you accept all the +terms in this License Agreement ("Agreement"). + +IMPORTANT: READ THE FOLLOWING TERMS AND CONDITIONS BEFORE USING THE +ACCOMPANYING NVIDIA GAMEWORKS SDK. + +IF YOU DO NOT AGREE TO THE TERMS OF THIS AGREEMENT, NVIDIA IS NOT +WILLING TO LICENSE THE NVIDIA GAMEWORKS SDK TO YOU AND YOU SHALL NOT +USE THIS SDK OR ANY PART OF IT. + +*Note: this End User License Agreement applies to GameWorks Modules +downloaded in binary (compiled) form. This End User License Agreement +does not apply to GameWorks Source Code. For GameWorks Source Code, +please refer to:* GameWorks Source SDK EULA (please log into NVIDIA +Registered Developer Program to see this document). + +1. Definitions. + +“NVIDIA GameWorks Application” means a software application designed for +use and fully compatible with the NVIDIA Graphics processor products, +including but not limited to, a video game, visual simulation, movie, or +other product. + +"NVIDIA GameWorks Binary SDK" means the set of instructions for +computers, in executable form only and in any media (which may include +diskette, CD-ROM, downloadable internet, hardware, or firmware) +comprising NVIDIA's proprietary Software Development Kit (in compiled or +binary form) and related media and printed materials, including +reference guides, documentation, and other manuals, installation +routines and support files, libraries, sample art files and assets, +tools, support utilities and any subsequent updates or adaptations +provided by NVIDIA, whether with this installation or as separately +downloaded (unless containing their own separate license terms and +conditions). + +“Sample Code” means the sample interface or application source and +object code files contained within the particular GameWorks SDK’s +“Samples” directory or made available for download from the NVIDIA +GameWorks developer site and designated as sample code. + +2. License. Subject to the terms and conditions of this Agreement, +NVIDIA grants you (“you”) a limited, non-exclusive, non-transferable +world-wide, royalty-free license to (a) internally install, use and +display the NVIDIA GAMEWORKS SDK, solely for purposes of developing +NVIDIA GameWorks asset content for NVIDIA GameWorks Applications; (b) +internally use, copy, modify and compile the Sample Code to design, +develop and test NVIDIA GameWorks assets; and (c) reproduce and +distribute the Redistributable Code only in object code form and only +as fully integrated into NVIDIA GameWorks Applications, in each case +solely for your commercial and non-commercial purposes provided that +your NVIDIA GameWorks Applications run solely on Windows PCs . + +In addition, you may not and shall not permit others to: + +I. modify, reproduce, de-compile, reverse engineer or translate the +NVIDIA GameWorks SDK; or +II. distribute or transfer the NVIDIA GameWorks SDK other than as +part of the NVIDIA GameWorks Application. + +Except as expressly granted herein, no other license under any +patent, copyright, trade secret, trademark or other intellectual +property right is granted to or conferred upon you by this Agreement. +All other rights are expressly reserved by NVIDIA and its licensors. + +3. Redistribution; NVIDIA GameWorks Applications. Any redistribution of +the NVIDIA GameWorks SDK (in accordance with Section 2 above) or +portions thereof must be subject to an end user license agreement +including language that + +a) prohibits the end user from modifying, reproducing, de-compiling, +reverse engineering or translating the NVIDIA GameWorks SDK; +b) prohibits the end user from distributing or transferring the NVIDIA +GameWorks SDK other than as part of the NVIDIA GameWorks Application; +c) disclaims any and all warranties on behalf of NVIDIA and its +affiliated companies and licensors; +d) disclaims, to the maximum extent permitted by law, NVIDIA’s, its +affiliated companies and its licensors' liability for all damages, +direct or indirect, incidental or consequential, that may arise from any +use of the NVIDIA GameWorks SDK and/or NVIDIA GameWorks Application; +e) requires the end user to agree not to export the NVIDIA GameWorks +SDK and/or NVIDIA GameWorks Application, directly or indirectly, in +violation of any U.S. laws; and + +You are required to notify NVIDIA prior to use of the NVIDIA GameWorks +SDK in the development of any commercial Application. Please send +notification by email to: gameworkslicensing@nvidia.com and provide the +following information in the email: + + * Company Name + * Publisher and Developer Name + * Game Title or Application Name + * Platforms (i.e. PC, Xbox, PlayStation) + * Scheduled Ship Date + * WebLink to product/video + +Any Application integrating the NVIDIA GameWorks SDK is subject to a +license to NVIDIA for use and public display of such Application for +advertising and marketing purposes. + +Failure to notify NVIDIA pursuant to this Section AND FAILURE to provide +attribution pursuant to section 6 shall be considered a material breach +of this agreement. + +4. Ownership, Protections. The NVIDIA GameWorks SDK is owned by NVIDIA +and NVIDIA licensors, and is protected by United States copyright laws, +international treaty provisions, and other applicable laws. With regard +to any copies made, you agree to reproduce any copyright notices and +other proprietary legends included on the original. NVIDIA +copyright notice(s) may appear in any of several forms, including +machine-readable form, and you agree to reproduce such notice in each +form in which it appears. Title and copyrights to the NVIDIA GameWorks +SDK and any copies made by you remain with NVIDIA and its licensors. +You acknowledge that the NVIDIA GameWorks SDK contain valuable +proprietary information and trade secrets and that unauthorized or +improper use of the NVIDIA GameWorks SDK will result in irreparable harm +to NVIDIA and its licensors for which monetary damages would be +inadequate and for which NVIDIA and its licensors will be entitled to +immediate injunctive relief. Subject to the rights of NVIDIA and its +licensors in the NVIDIA GameWorks SDK and the Sample Code, you own your +modifications to the Sample Code. + +5. Restrictions. You will not, and will not permit others to: (a) +modify, translate, decompile, bootleg, reverse engineer, disassemble, or +extract the inner workings of any portion of the NVIDIA GameWorks SDK +except the Sample Code, (b) copy the look-and-feel or functionality of +any portion of the NVIDIA GameWorks SDK except the Sample Code; (c) +remove any proprietary notices, marks, labels, or logos from the NVIDIA +GameWorks SDK or any portion thereof; (d) rent, transfer or use as a +service bureau all or some of the NVIDIA GameWorks SDK without NVIDIA’s +prior written consent, except in the form of Applications and subject to +the requirements of this Agreement; (e) utilize any computer software or +hardware which is designed to defeat any copy protection device, should +the NVIDIA GameWorks SDK be equipped with such a protection device; or +(f) use the NVIDIA Licensed Software in any manner that would cause the +NVIDIA Licensed Software to become subject to an Open Source License. +"Open Source License" includes, without limitation, a software license +that requires as a condition of use, modification, and/or distribution +of such software that the NVIDIA Licensed Software be (i) disclosed or +distributed in source code form; (ii) be licensed for the purpose of +making derivative works; or (iii) be redistributable at no charge. +Unauthorized copying of the NVIDIA GameWorks SDK, or failure to comply +with any of the provisions of this Agreement, will result in automatic +termination of this license. + +6. Attribution Requirements and Trademark License. You must provide +attribution to NVIDIA. + +A. You will include a reference to the NVIDIA GameWorks and NVIDIA in +any press releases for such Game/Application that relate to NVIDIA, or +in-game NVIDIA GameWorks technology, and will identify NVIDIA as the +provider of "NVIDIA GameWorks" (or such other term or phrase as +indicated by NVIDIA from time to time). + +B. For Games, Demos, and Videos that incorporate the NVIDIA GameWorks +SDK or portions thereof, the NVIDIA GameWorks logos must appear: + +a. on the back cover of the instruction manual or similar placement in +an electronic file for the purpose of +acknowledgement/copyright/trademark notice; +b. on external packaging; +c. during opening marquee or credits with inclusion of “NVIDIA”; +d. must appear on title marketing feature list with a specific +call-out of NVIDIA GameWorks Technology +e. on the credit screen; and +f. in the “About” or “Info” box menu items (or equivalent) +of all Games or Applications using any portion of the NVIDIA +GameWorks SDK. + +C. Provide a quote citing yourthe Licensee’s integration of the NVIDIA +GameWorks SDK into the Game or Application for NVIDIA’s use in press +materials and website. + +D. Refer to NVIDIA GameWorks in all press coverage referring to the +use NVIDIA GameWorks technology in the development of any Game or +Application. + +E. Identification by NVIDIA. Subject to the terms and conditions of +this Agreement, you agree that NVIDIA may identify you, on NVIDIA's +website, printed collateral, trade-show displays and other retail +packaging materials, as a company that produces products and/or services +which incorporate the NVIDIA Gameworks SDK. To the extent that you +provide NVIDIA with input or usage requests with regard to the use of +your logo or materials, NVIDIA will use commercially reasonable efforts +to comply with such requests. For the avoidance of doubt, NVIDIA’s +rights pursuant to this Section 6(E) shall survive any cancellation or +termination of the Agreement with respect to existing products and/or +services which incorporate the NVIDIA GameWorks SDK. + +F. Game/Demo-related Marketing Material. You permit NVIDIA to create +and display self-promotional demo materials and use screenshot materials +that capture game assets from real-time game play, captured video clips +and images from the Game, after release of the Game to the public, and +you may also provide NVIDIA with screenshots / imagery and video footage +of the Game/Demo representative of your use of the NVIDIA Gameworks SDK +in the Game (collectively, “Assets”). You hereby grant to NVIDIA the +right to distribute, sub-license, and use the Assets in order to promote +and market the NVIDIA GameWorks SDK. To the extent that Company provides +NVIDIA with input or usage requests with regard to the use of your logo +or materials, NVIDIA will use commercially reasonable efforts to comply +with such requests. For the avoidance of doubt, NVIDIA’s rights +pursuant to this Section 6(F) shall survive any cancellation or +termination of the Agreement with respect to Applications which +incorporate the NVIDIA GameWorks SDK. + +Failure to provide attribution pursuant to this Section shall be +considered a material breach of this agreement. + +Except as expressly set forth in this Section 6, or in a separate +written agreement with NVIDIA, you may not use NVIDIA's trademarks, +whether registered or unregistered, in connection with the Application +in any manner or imply that NVIDIA endorses or otherwise approves of the +Application or that you and NVIDIA are in any way affiliated. Your use +of the NVIDIA name under this Agreement does not create any right, title +or interest in the NVIDIA name or any NVIDIA trademarks and all goodwill +arising from your use inure solely to the benefit of NVIDIA. + +7. DISCLAIMER. THE NVIDIA GAMEWORKS SDK IS PROVIDED “AS IS” AND NVIDIA +AND ITS LICENSORS MAKE, AND YOU RECEIVE, NO OTHER WARRANTIES OF ANY +KIND, WHETHER EXPRESS, IMPLIED, STATUTORY, OR IN ANY COMMUNICATION WITH +YOU. NVIDIA SPECIFICALLY DISCLAIMS ANY OTHER WARRANTY INCLUDING THE +IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR +A PARTICULAR PURPOSE. NVIDIA DOES NOT WARRANT THAT THE OPERATION OF THE +SOFTWARE WILL BE UNINTERRUPTED OR ERROR FREE OR THAT DEFECTS IN THE +SOFTWARE WILL BE CORRECTED. NVIDIA MAKES NO WARRANTY WITH RESPECT TO +THE CORRECTNESS, ACCURACY, OR RELIABILITY OF THE SOFTWARE AND +DOCUMENTATION. Some jurisdictions do not allow the exclusion of implied +warranties, so the above exclusion may not apply to you. + + +8. Confidential Information. All technical and business information +disclosed by NVIDIA to you under this Agreement, including but not +limited to source code, documentation, technical assistance and any +confidential information pertaining to NVIDIA’s business or products, +are to be considered “NVIDIA Confidential Information.” You will not +disclose any portion of NVIDIA Confidential Information to any third +party and will protect all NVIDIA Confidential Information with the same +degree of care as you use to protect your own information of a +confidential or proprietary nature, but always with at least a +reasonable degree of care. This obligation of confidentiality will +survive termination and/or expiration of this Agreement for any reason. + +9. LIMITATION OF LIABILITY. THE TOTAL LIABILITY OF NVIDIA AND ITS +LICENSORS UNDER THIS AGREEMENT FOR DAMAGES WILL NOT EXCEED $100 IN THE +AGGREGATE. IN NO EVENT WILL NVIDIA OR ITS LICENSORS BE LIABLE IN ANY +WAY FOR INCIDENTAL, CONSEQUENTIAL, INDIRECT, SPECIAL OR PUNITIVE DAMAGES +OF ANY NATURE, INCLUDING WITHOUT LIMITATION, LOST BUSINESS PROFITS, OR +LIABILITY OR INJURY TO THIRD PERSONS, WHETHER FORESEEABLE OR NOT, +REGARDLESS OF WHETHER NVIDIA OR ITS LICENSORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. Some jurisdictions do not permit +limitations of liability for incidental or consequential damages, so the +above exclusions may not apply to you. + + +10. Term of License; Termination. Your right to use the NVIDIA +GameWorks SDK will begin when you click the “ACCEPT” button, which +constitutes acceptance of the terms and conditions herein. The license +is effective until otherwise terminated. You may terminate it at any +time by destroying the NVIDIA GameWorks SDK and all portions thereof, +together with all copies in any form. If you fail to comply with any +material term or condition of this Agreement and do not cure the +noncompliance within 30 days of receipt of written notice of +noncompliance from NVIDIA, NVIDIA may terminate your rights to conduct +any further development under Sections 2(a) and (b) of this Agreement +("Partial Termination"). Upon Partial Termination, you will certify to +NVIDIA in writing that the original and all stand-alone copies, in whole +or in part, of the NVIDIA GameWorks SDK have been destroyed. Upon +Partial Termination, you may continue to distribute any Application that +has been commercially released prior to such termination subject to +prospective compliance with this Agreement. Upon any other termination, +you will certify to NVIDIA in writing that the original and all copies, +in whole or in part, of the NVIDIA GameWorks SDK have been destroyed, +including those portions contained within any unshipped Applications. + +11. Governing Law. This Agreement will be governed by the laws of the +United States of America to the extent that they apply and otherwise by +the laws of the State of Delaware notwithstanding the application of any +conflicts of law rules. Exclusive venue over all disputes arising under +or relating to this Agreement shall be in the federal or state courts of +Santa Clara County, California. . + +12. Export. You agree and certify that no portion of the NVIDIA +GameWorks SDK nor any other technical data received from NVIDIA will be +exported outside the United States except as authorized and as permitted +by the laws and regulations of the United States. If you have rightfully +obtained the NVIDIA GameWorks SDK outside of the United States, you +agree that you will not re-export any portion of the NVIDIA GameWorks +SDK nor any other technical data received from NVIDIA, except as +permitted by the laws and regulations of the United States and the laws +and regulations of the jurisdiction in which you obtained the NVIDIA +GameWorks SDK. + +13. Assignment. You may not sublicense, assign or transfer this +Agreement or the NVIDIA GameWorks SDK except as expressly provided in +this Agreement. Any attempt to otherwise sublicense, assign or transfer +any of the rights, duties or obligations hereunder is null and void. + +14. Survival. The parties agree that where the context of any provision +indicates an intent that it will survive the term of this Agreement, +then it will survive. All terms of this Agreement survive Partial +Termination except Sections 2(a) and (b). + +15. Entire Agreement. This Agreement contains the parties’ entire +agreement regarding your use +of the NVIDIA GameWorks SDK and may be amended only in writing signed by +both parties. Copyright © 2014 NVIDIA Corporation. All rights reserved. + +US AND INTERNATIONAL PATENTS PENDING. diff --git a/docs/GhostingEverywhere.jpg b/docs/GhostingEverywhere.jpg new file mode 100644 index 0000000..8e9313f Binary files /dev/null and b/docs/GhostingEverywhere.jpg differ diff --git a/docs/ImageAcne.jpg b/docs/ImageAcne.jpg new file mode 100644 index 0000000..904b244 Binary files /dev/null and b/docs/ImageAcne.jpg differ diff --git a/docs/ImageWithoutAcne.jpg b/docs/ImageWithoutAcne.jpg new file mode 100644 index 0000000..a7a2ab6 Binary files /dev/null and b/docs/ImageWithoutAcne.jpg differ diff --git a/docs/NvCameraConfiguration.exe_screen.png b/docs/NvCameraConfiguration.exe_screen.png new file mode 100644 index 0000000..a96ad64 Binary files /dev/null and b/docs/NvCameraConfiguration.exe_screen.png differ diff --git a/docs/ScreenSpaceReflections.jpg b/docs/ScreenSpaceReflections.jpg new file mode 100644 index 0000000..8fec9bc Binary files /dev/null and b/docs/ScreenSpaceReflections.jpg differ diff --git a/docs/ScreenSpaceReflectionsReduced.jpg b/docs/ScreenSpaceReflectionsReduced.jpg new file mode 100644 index 0000000..a69aadc Binary files /dev/null and b/docs/ScreenSpaceReflectionsReduced.jpg differ diff --git a/docs/StreakyReflections.jpg b/docs/StreakyReflections.jpg new file mode 100644 index 0000000..1fb5fd1 Binary files /dev/null and b/docs/StreakyReflections.jpg differ diff --git a/include/AnselSDK.h b/include/AnselSDK.h new file mode 100644 index 0000000..ddf5197 --- /dev/null +++ b/include/AnselSDK.h @@ -0,0 +1,33 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2015 NVIDIA Corporation. All rights reserved. + +#pragma once + +#include +#include +#include +#include diff --git a/include/ansel/Camera.h b/include/ansel/Camera.h new file mode 100644 index 0000000..cdd3d9f --- /dev/null +++ b/include/ansel/Camera.h @@ -0,0 +1,63 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2015 NVIDIA Corporation. All rights reserved. + +#pragma once +#include +#include +#include + +namespace ansel +{ + struct Camera + { + // Position of camera, in the game's coordinate space + nv::Vec3 position; + // Rotation of the camera, in the game's coordinate space. I.e. if you apply this + // rotation to the default orientation of the game's camera you will get the current + // orientation of the camera (again, in game's coordinate space) + nv::Quat rotation; + // Field of view in degrees. This value is either vertical or horizontal field of + // view based on the 'fovType' setting passed in with setConfiguration. + float fov; + // The amount that the projection matrix needs to be offset by. These values are + // applied directly as translations to the projection matrix. These values are only + // non-zero during Highres capture. + float projectionOffsetX, projectionOffsetY; + }; + + // Must be called on every frame an Ansel session is active. The 'camera' must contain + // the current display camera settings when called. After calling 'camera' will contain the + // new requested camera from Ansel. + ANSEL_SDK_API void updateCamera(Camera& camera); + + // Converts quaternion to rotation matrix vectors. + ANSEL_SDK_API void quaternionToRotationMatrixVectors(const nv::Quat& q, nv::Vec3& right, nv::Vec3& up, nv::Vec3& forward); + + // Converts rotation matrix vectors to quaternion. + ANSEL_SDK_API void rotationMatrixVectorsToQuaternion(const nv::Vec3& right, const nv::Vec3& up, const nv::Vec3& forward, nv::Quat& q); +} + diff --git a/include/ansel/Configuration.h b/include/ansel/Configuration.h new file mode 100644 index 0000000..e172e57 --- /dev/null +++ b/include/ansel/Configuration.h @@ -0,0 +1,180 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2015 NVIDIA Corporation. All rights reserved. + +#pragma once +#include +#include +#include +#include +#include + +namespace ansel +{ + enum SetConfigurationStatus + { + // successfully initialized the Ansel SDK + kSetConfigurationSuccess, + // the version provided in the Configuration structure is not the same as the one stored inside the SDK binary (header/binary mismatch) + kSetConfigurationIncompatibleVersion, + // the Configuration structure supplied for the setConfiguration call is not consistent + kSetConfigurationIncorrectConfiguration, + // the Ansel SDK is delay loaded and setConfiguration is called before the SDK is actually loaded + kSetConfigurationSdkNotLoaded + }; + + enum FovType + { + kHorizontalFov, + kVerticalFov + }; + + struct Configuration + { + // Basis vectors used by the game. They specify the handedness and orientation of + // the game's coordinate system. Think of them as the default orientation of the game + // camera. + nv::Vec3 right, up, forward; + // The speed at which camera moves in the world + float translationalSpeedInWorldUnitsPerSecond; + // The speed at which camera rotates + float rotationalSpeedInDegreesPerSecond; + // How many frames it takes for camera update to be reflected in a rendered frame + uint32_t captureLatency; + // How many frames we must wait for a new frame to settle - i.e. temporal AA and similar + // effects to stabilize after the camera has been adjusted + uint32_t captureSettleLatency; + // Game scale, the size of a world unit measured in meters + float metersInWorldUnit; + // Integration will support Camera::screenOriginXOffset/screenOriginYOffset + bool isCameraOffcenteredProjectionSupported; + // Integration will support Camera::position + bool isCameraTranslationSupported; + // Integration will support Camera::rotation + bool isCameraRotationSupported; + // Integration will support Camera::horizontalFov + bool isCameraFovSupported; + // Game name, in utf8 encoding, used to name the resulting image files from capturing. + // It is not mandatory to set this field. The name chosen is based on the following + // selection order: + // 1. If GeForce profile exists for the game that name will be used + // 2. If 'titleNameUtf8' is set that will be used + // 3. The executable name is used as a last resort + const char* titleNameUtf8; + // Camera structure will contain vertical FOV if this is set to kVerticalFov + // but horizontal FOV if this is set to kHorizontalFov. To simplify integration set + // this to the same orientation as the game is using. + FovType fovType; + + // These callbacks will be called on the same thread Present()/glSwapBuffers is called + // The thread calling to updateCamera() might be a different thread + + // User defined pointer which is then passed to all the callbacks (nullptr by default) + void* userPointer; + + // The window handle for the game/application where input messages are processed + void* gameWindowHandle; + + // Called when user activates Ansel. Return false if the game cannot comply with the + // request. If the function returns true the following must be done: + // 1. Change the SessionConfigruation settings, but only where you need to (the object + // is already populated with default settings). + // 2. On the next update loop the game will be in an Ansel session. This requires the game + // to + // a) stop drawing any UI or HUD related elements + // b) pause the simulation (if possible) + // c) call ansel::updateCamera and perform associated processing + // 3. Step 2 is repeated on every iteration of update loop until Session is stopped. + StartSessionCallback startSessionCallback; + + // Called when Ansel is deactivated. This call will only be made if the previous call + // to the startSessionCallback returned true. + // Normally games will use this callback to restore their camera to the settings it had + // when the Ansel session was started. + StopSessionCallback stopSessionCallback; + + // Called when the capture of a multipart shot (highres, 360, etc) has started. + // Handy to disable those fullscreen effects that aren't uniform (like vignette) + // This callback is optional (leave nullptr if not needed) + StartCaptureCallback startCaptureCallback; + // Called when the capture of a multipart shot (highres, 360, etc) has stopped. + // Handy to enable those fullscreen effects that were disabled by startCaptureCallback. + // This callback is optional (leave nullptr if not needed) + StopCaptureCallback stopCaptureCallback; + // Integration allows a filter/effect to remain active when the Ansel session is not active + bool isFilterOutsideSessionAllowed; + // The 'isExrSupported' setting has been phased out in version 1.1 of the SDK. Use + // 'isRawAllowed' setting in SessionConfiguration to enable/disable captures into EXR + // format. + bool unused1; + // Holds the sdk version, doesn't require modifications + uint64_t sdkVersion; + + Configuration() + { + right.x = 0.0f; + right.y = 1.0f; + right.z = 0.0f; + up.x = 0.0f; + up.y = 0.0f; + up.z = 1.0f; + forward.x = 1.0f; + forward.y = 0.0f; + forward.z = 0.0f; + translationalSpeedInWorldUnitsPerSecond = 1.0f; + rotationalSpeedInDegreesPerSecond = 45.0f; + captureLatency = 1; + captureSettleLatency = 0; + metersInWorldUnit = 1.0f; + isCameraOffcenteredProjectionSupported = true; + isCameraTranslationSupported = true; + isCameraRotationSupported = true; + isCameraFovSupported = true; + titleNameUtf8 = nullptr; + fovType = kHorizontalFov; + userPointer = nullptr; + gameWindowHandle = 0; + startSessionCallback = nullptr; + stopSessionCallback = nullptr; + startCaptureCallback = nullptr; + stopCaptureCallback = nullptr; + isFilterOutsideSessionAllowed = true; + unused1 = false; + sdkVersion = ANSEL_SDK_VERSION; + } + }; + + // Called during startup by the game. See 'Configuration' for further documentation. + ANSEL_SDK_API SetConfigurationStatus setConfiguration(const Configuration& cfg); + + // Can be called *after* D3D device has been created to see if Ansel is available. + // If called prior to D3D device creation it will always return false. + // Can be called *before* calling setConfiguration in which case it'll return true if Ansel is potentially available, otherwise false. + // If setConfiguration fails for any reason this function will return false (even if Ansel would be available otherwise) + // until a successfull call to setConfiguration has been made. + ANSEL_SDK_API bool isAnselAvailable(); +} + diff --git a/include/ansel/Defines.h b/include/ansel/Defines.h new file mode 100644 index 0000000..56e76bc --- /dev/null +++ b/include/ansel/Defines.h @@ -0,0 +1,39 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2015 NVIDIA Corporation. All rights reserved. + +#pragma once + +#ifdef ANSEL_SDK_EXPORTS + #define ANSEL_SDK_API extern "C" __declspec(dllexport) + #define ANSEL_SDK_CLASS_API __declspec(dllexport) +#elif !defined(ANSEL_SDK_DELAYLOAD) + #define ANSEL_SDK_API extern "C" __declspec(dllimport) + #define ANSEL_SDK_CLASS_API __declspec(dllimport) +#else + #define ANSEL_SDK_API + #define ANSEL_SDK_CLASS_API +#endif diff --git a/include/ansel/Hints.h b/include/ansel/Hints.h new file mode 100644 index 0000000..81068a7 --- /dev/null +++ b/include/ansel/Hints.h @@ -0,0 +1,67 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2015 NVIDIA Corporation. All rights reserved. + +#pragma once +#include +#include + +namespace ansel +{ + enum HintType + { + kHintTypePreBind, + kHintTypePostBind + }; + + enum HintThreadingBehaviour + { + kThreadingBehaviourMatchAutomatic = 0, + kThreadingBehaviourNoMatching = 0xFFFFFFFFFFFFFFFFull + }; + + // Call this right before setting HDR render target active + // hintType is an optional argument specifying what type of hint is this - + // it could be called after or before the bind of a buffer that this hint marks. + // The default option is kHintTypePreBind, which means the hint should be called before + // the render target is bound. + // threadId is an optional argument allowing Ansel to match the thread which calls + // SetRenderTarget (or analogous function, since this is graphics API dependent) + // to the thread which called the hint. The default value of kNoMatching + // means that no such matching is going to happen. The special value of 0 means that + // Ansel SDK is going to match thread ids automatically. Any other value means a specific thread id + // known at integration side. + ANSEL_SDK_API void markHdrBufferBind(HintType hintType = kHintTypePreBind, uint64_t threadId = kThreadingBehaviourNoMatching); + // Call this right after the last draw call into the HDR render target + // threadId is an optional argument allowing Ansel to match the thread which calls + // SetRenderTarget (or analogous function, since this is graphics API dependent) + // to the thread which called the hint. The default value of kNoMatching + // means that no such matching is going to happen. The special value of 0 means that + // Ansel SDK is going to match thread ids automatically. Any other value means a specific thread id + // known at integration side. + ANSEL_SDK_API void markHdrBufferFinished(uint64_t threadId = kThreadingBehaviourNoMatching); +} + diff --git a/include/ansel/Session.h b/include/ansel/Session.h new file mode 100644 index 0000000..53520e4 --- /dev/null +++ b/include/ansel/Session.h @@ -0,0 +1,105 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2015 NVIDIA Corporation. All rights reserved. + +#pragma once +#include + +namespace ansel +{ + struct SessionConfiguration + { + // User can move the camera during session + bool isTranslationAllowed; + // Camera can be rotated during session + bool isRotationAllowed; + // FoV can be modified during session + bool isFovChangeAllowed; + // Game is paused during session + bool isPauseAllowed; + // Game allows highres capture during session + bool isHighresAllowed; + // Game allows 360 capture during session + bool is360MonoAllowed; + // Game allows 360 stereo capture during session + bool is360StereoAllowed; + // Game allows capturing pre-tonemapping raw HDR buffer + bool isRawAllowed; + // The speed at which camera moves in the world, initialized with a value given in Configuration + float translationalSpeedInWorldUnitsPerSecond; + // The speed at which camera rotates, initialized with a value given in Configuration + float rotationalSpeedInDegreesPerSecond; + + SessionConfiguration() + { + isTranslationAllowed = true; + isRotationAllowed = true; + isFovChangeAllowed = true; + isPauseAllowed = true; + isHighresAllowed = true; + is360MonoAllowed = true; + is360StereoAllowed = true; + isRawAllowed = true; + } + }; + + enum StartSessionStatus + { + kDisallowed = 0, + kAllowed + }; + + enum CaptureType + { + kCaptureType360Mono = 0, + kCaptureType360Stereo, + kCaptureTypeSuperResolution, + kCaptureTypeStereo + }; + + struct CaptureConfiguration + { + CaptureType captureType; + }; + + typedef StartSessionStatus(*StartSessionCallback)(SessionConfiguration& settings, void* userPointer); + typedef void(*StopSessionCallback)(void* userPointer); + typedef void(*StartCaptureCallback)(const CaptureConfiguration&, void* userPointer); + typedef void(*StopCaptureCallback)(void* userPointer); + + // Starts a session if there is not one already active. This function can be used to trigger + // Ansel via any method that the game chooses (key combination, controller input, etc) + ANSEL_SDK_API void startSession(); + + // Stops current session if there is one active. This function needs to be used if the + // startSession function was used to implement custom activation method. The same custom + // activation method needs to used to deactivate Ansel. If for instance left-stick pressed + // was used for startSession then the same should be used for stopping the Ansel session. + // This function can also be used if Ansel session needs to be interrupted + // (for instance an online game where connection loss is experienced and needs to be + // reported). + ANSEL_SDK_API void stopSession(); +} \ No newline at end of file diff --git a/include/ansel/Version.h b/include/ansel/Version.h new file mode 100644 index 0000000..27f9d2b --- /dev/null +++ b/include/ansel/Version.h @@ -0,0 +1,52 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2016 NVIDIA Corporation. All rights reserved. + +#pragma once + +// These are the version numbers used to version the API between Ansel SDK and the driver. +// The driver provides backwards compatibility to all MINOR versions that are equal or lower +// but requires matching MAJOR version. This effectively means that MAJOR version number will *not* +// change because this would mean that a newer driver would stop supporting older Ansel SDKs. +// The driver does however not provide forwards compatibility, i.e. when a new interface or change +// in behavior is introduced between Ansel SDK and the driver the MINOR version is incremented. This +// means that new driver supporting this new MINOR version is required. To track this relationship +// we use the MINIMUM_DRIVER_VERSION define. When you increment MINOR version you need to adjust the +// MINIMUM_DRIVER_VERSION as well. While a public driver hasn't been finalized use our internal +// release tags to identify it (like 378.GA2). +#define ANSEL_SDK_PRODUCT_VERSION_MAJOR 1 +#define ANSEL_SDK_PRODUCT_VERSION_MINOR 1 +#define ANSEL_SDK_MINIMUM_DRIVER_VERSION "378.49" + +// The lines below are automatically updated by build agents. Please don't touch. +// The BUILD_NUMBER and COMMIT_HASH are useful in uniquely identifying a build of the Ansel SDK. +// Changes to the customer facing API can be tracked with these since they are automatically +// updated every time a change is made. +#define ANSEL_SDK_BUILD_NUMBER 1027 +#define ANSEL_SDK_COMMIT_HASH 0x6e9b4e3a + +#define ANSEL_SDK_VERSION ( uint64_t(ANSEL_SDK_PRODUCT_VERSION_MAJOR) << 48 | uint64_t(ANSEL_SDK_PRODUCT_VERSION_MINOR) << 32 \ + | ANSEL_SDK_COMMIT_HASH ) diff --git a/include/nv/Quat.h b/include/nv/Quat.h new file mode 100644 index 0000000..94a4b44 --- /dev/null +++ b/include/nv/Quat.h @@ -0,0 +1,10 @@ +#pragma once + +namespace nv +{ + struct Quat + { + float x, y, z, w; + }; +} + diff --git a/include/nv/Vec3.h b/include/nv/Vec3.h new file mode 100644 index 0000000..e7e7d86 --- /dev/null +++ b/include/nv/Vec3.h @@ -0,0 +1,12 @@ +#pragma once + +namespace nv +{ + +struct Vec3 +{ + float x, y, z; +}; + + +} // end of nv namspace \ No newline at end of file diff --git a/samples/AnselSDKDelayLoader/AnselSDKDelayLoader.vcxproj b/samples/AnselSDKDelayLoader/AnselSDKDelayLoader.vcxproj new file mode 100644 index 0000000..bd22385 --- /dev/null +++ b/samples/AnselSDKDelayLoader/AnselSDKDelayLoader.vcxproj @@ -0,0 +1,228 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + {396213D4-2D38-497D-A4F0-530E7B136874} + Win32Proj + AnselSDK + 8.1 + AnselSDKDelayLoader + + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + true + lib\$(Platform)\ + intermediate\$(TargetName)\$(Platform)\$(Configuration)\ + true + .lib + $(ProjectName)32d + + + true + lib\$(Platform)\ + intermediate\$(TargetName)\$(Platform)\$(Configuration)\ + true + .lib + $(ProjectName)64d + + + false + lib\$(Platform)\ + intermediate\$(TargetName)\$(Platform)\$(Configuration)\ + true + .lib + $(ProjectName)32 + + + false + lib\$(Platform)\ + intermediate\$(TargetName)\$(Platform)\$(Configuration)\ + true + .lib + $(ProjectName)64 + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + ../../include;source + MultiThreadedDebug + 4350;4514;4625;4626;4710;4711;4820;%(DisableSpecificWarnings) + ProgramDatabase + Async + false + true + Guard + true + + + Windows + true + lib\$(Platform)\$(TargetName).lib + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + ../../include;source + MultiThreadedDebug + 4350;4514;4625;4626;4710;4711;4820;%(DisableSpecificWarnings) + Guard + Async + ProgramDatabase + false + true + true + + + Windows + true + lib\$(Platform)\$(TargetName).lib + + + + + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + ../../include;source + MultiThreaded + 4350;4514;4625;4626;4710;4711;4820;%(DisableSpecificWarnings) + Async + false + Default + true + Guard + true + + + Windows + true + true + true + lib\$(Platform)\$(TargetName).lib + + + + + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + ../../include;source + MultiThreaded + 4350;4514;4625;4626;4710;4711;4820;%(DisableSpecificWarnings) + Async + false + Default + true + Guard + true + + + Windows + true + true + true + lib\$(Platform)\$(TargetName).lib + + + + + + + + + + \ No newline at end of file diff --git a/samples/AnselSDKDelayLoader/AnselSDKDelayLoader.vcxproj.filters b/samples/AnselSDKDelayLoader/AnselSDKDelayLoader.vcxproj.filters new file mode 100644 index 0000000..02614af --- /dev/null +++ b/samples/AnselSDKDelayLoader/AnselSDKDelayLoader.vcxproj.filters @@ -0,0 +1,19 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + h;hpp;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + + + Source Files + + + \ No newline at end of file diff --git a/samples/AnselSDKDelayLoader/source/DelayLoader.cpp b/samples/AnselSDKDelayLoader/source/DelayLoader.cpp new file mode 100644 index 0000000..6b837fb --- /dev/null +++ b/samples/AnselSDKDelayLoader/source/DelayLoader.cpp @@ -0,0 +1,281 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2016 NVIDIA Corporation. All rights reserved. + + +#define ANSEL_SDK_DELAYLOAD +#include "DelayLoader.h" +#include +#include +#include +#include +#include +#include +#include + + +namespace +{ + HMODULE anselSDK = NULL; +} + +namespace ansel +{ + namespace + { + typedef SetConfigurationStatus(__cdecl *PFNSETCONFIGURATION)(const Configuration& cfg); + typedef void(__cdecl *PFNUPDATECAMERA)(Camera& camera); + typedef void(__cdecl *PFNSESSIONFUNC)(); + typedef bool(__cdecl *PFNISANSELAVAILABLE)(); + typedef void(__cdecl *PFNMARKHDRBUFFERBIND)(HintType, uint64_t); + typedef void(__cdecl *PFNMARKHDRBUFFERFINISHED)(uint64_t); + PFNMARKHDRBUFFERFINISHED markHdrBufferFinishedFunc = nullptr; + PFNMARKHDRBUFFERBIND markHdrBufferBindFunc = nullptr; + PFNSESSIONFUNC stopSessionFunc = nullptr; + PFNSESSIONFUNC startSessionFunc = nullptr; + PFNUPDATECAMERA updateCameraFunc = nullptr; + PFNSETCONFIGURATION setConfigurationFunc = nullptr; + + DelayLoadStatus resolveFunctionPointers() + { + if (anselSDK == NULL) + return kDelayLoadDllNotFound; + + setConfigurationFunc = reinterpret_cast(GetProcAddress(anselSDK, "setConfiguration")); + stopSessionFunc = reinterpret_cast(GetProcAddress(anselSDK, "stopSession")); + startSessionFunc = reinterpret_cast(GetProcAddress(anselSDK, "startSession")); + updateCameraFunc = reinterpret_cast(GetProcAddress(anselSDK, "updateCamera")); + markHdrBufferBindFunc = reinterpret_cast(GetProcAddress(anselSDK, "markHdrBufferBind")); + markHdrBufferFinishedFunc = reinterpret_cast(GetProcAddress(anselSDK, "markHdrBufferFinished")); + + if (setConfigurationFunc == nullptr || + stopSessionFunc == nullptr || + startSessionFunc == nullptr || + updateCameraFunc == nullptr || + markHdrBufferBindFunc == nullptr || + markHdrBufferFinishedFunc == nullptr) + return kDelayLoadIncompatibleVersion; + + return kDelayLoadOk; + } + + void makeQuaternionFromRotationMatrix(nv::Quat& q, const float r[3][3]) + { + float trace = r[0][0] + r[1][1] + r[2][2]; + + if (trace > 0.0f) { + // |w| > 1/2, may as well choose w > 1/2 + float s = sqrtf(trace + 1.0f); // 2w + + q.w = s * 0.5f; + s = 0.5f / s; // 1/(4w) + + q.x = (r[2][1] - r[1][2]) * s; + q.y = (r[0][2] - r[2][0]) * s; + q.z = (r[1][0] - r[0][1]) * s; + } + else { + // |w| <= 1/2 + int i = 0; + if (r[1][1] > r[0][0]) i = 1; + if (r[2][2] > r[i][i]) i = 2; + + int j = (1 << i) & 3; // i + 1 modulo 3. + int k = (1 << j) & 3; + + float s = sqrtf(r[i][i] - r[j][j] - r[k][k] + 1.0f); + + float* component = &q.x; + component[i] = s * 0.5f; + s = 0.5f / s; + component[j] = (r[i][j] + r[j][i]) * s; + component[k] = (r[k][i] + r[i][k]) * s; + q.w = (r[k][j] - r[j][k]) * s; + } + } + + void makeRotationMatrixFromQuaternion(float rot[3][3], const nv::Quat& q) + { + float s = 2.0f; + + float xs = q.x * s; + float ys = q.y * s; + float zs = q.z * s; + + float wx = q.w * xs; + float wy = q.w * ys; + float wz = q.w * zs; + + float xx = q.x * xs; + float xy = q.x * ys; + float xz = q.x * zs; + + float yy = q.y * ys; + float yz = q.y * zs; + float zz = q.z * zs; + + rot[0][0] = 1.0f - (yy + zz); + rot[0][1] = xy - wz; + rot[0][2] = xz + wy; + + rot[1][0] = xy + wz; + rot[1][1] = 1.0f - (xx + zz); + rot[1][2] = yz - wx; + + rot[2][0] = xz - wy; + rot[2][1] = yz + wx; + rot[2][2] = 1.0f - (xx + yy); + } + + // This may seem like a funky construct so allow me to explain. This code serves only + // one purpose: to create a signaling object that Ansel (when loaded from driver shim) + // can use to detect that a game has integrated the SDK. Note that this same object + // will also be created by the SDK DLL when loaded but this is safe since creating + // the same mutex again just provides a handle to the already existing mutex. + class SdkMutex + { + public: + SdkMutex() + { + DWORD id = GetCurrentProcessId(); + char name[MAX_PATH]; + sprintf_s(name, "NVIDIA/Ansel/%d", id); + CreateMutexA(NULL, false, name); + } + }; + + SdkMutex s_mySdkMutex; + } + + + SetConfigurationStatus setConfiguration(const Configuration& config) + { + if (setConfigurationFunc) + return setConfigurationFunc(config); + else + return kSetConfigurationSdkNotLoaded; + } + + void updateCamera(ansel::Camera& cam) + { + if (updateCameraFunc) + updateCameraFunc(cam); + } + + void stopSession() + { + if (stopSessionFunc) + stopSessionFunc(); + } + + void startSession() + { + if (startSessionFunc) + startSessionFunc(); + } + + bool isAnselAvailable() + { + // search for NvCamera32/64 DLL in the process + const char* moduleName = +#if _M_AMD64 + "NvCamera64.dll"; +#else + "NvCamera32.dll"; +#endif + + return GetModuleHandleA(moduleName) != nullptr; + } + + void markHdrBufferBind(HintType hintType, uint64_t threadId) + { + if (markHdrBufferBindFunc) + markHdrBufferBindFunc(hintType, threadId); + } + + void markHdrBufferFinished(uint64_t threadId) + { + if (markHdrBufferFinishedFunc) + markHdrBufferFinishedFunc(threadId); + } + + void quaternionToRotationMatrixVectors(const nv::Quat& q, nv::Vec3& right, nv::Vec3& up, nv::Vec3& forward) + { + float rot[3][3]; + makeRotationMatrixFromQuaternion(rot, q); + right = { rot[0][0], rot[1][0], rot[2][0] }; + up = { rot[0][1], rot[1][1], rot[2][1] }; + forward = { rot[0][2], rot[1][2], rot[2][2] }; + } + + void rotationMatrixVectorsToQuaternion(const nv::Vec3& right, const nv::Vec3& up, const nv::Vec3& forward, nv::Quat& q) + { + const float rot[3][3] = { + { right.x, up.x, forward.x }, + { right.y, up.y, forward.y }, + { right.z, up.z, forward.z } + }; + makeQuaternionFromRotationMatrix(q, rot); + } +} + +DelayLoadStatus loadAnselSDKLibrary(const char* pathToLibraryUtf8) +{ + if (anselSDK == NULL) + { + if (pathToLibraryUtf8) + { + // convert from utf8 to wchar_t: + std::wstring_convert> converter; + std::wstring pathWstring = converter.from_bytes(pathToLibraryUtf8); + anselSDK = LoadLibraryW(pathWstring.c_str()); + } + else + { + #if defined(_M_IX86) + #define ANSEL_BITNESS "32" + #elif defined(_M_AMD64) + #define ANSEL_BITNESS "64" + #endif + + #if defined(_DEBUG) + #define ANSEL_RUNTIME_FLAVOR "d" + #else + #define ANSEL_RUNTIME_FLAVOR "" + #endif + + const char* libName = "AnselSDK" ANSEL_BITNESS ANSEL_RUNTIME_FLAVOR ".dll"; + anselSDK = LoadLibraryA(libName); + } + + if (anselSDK == NULL) + return kDelayLoadDllNotFound; + else + return ansel::resolveFunctionPointers(); + } + + return kDelayLoadOk; +} diff --git a/samples/AnselSDKDelayLoader/source/DelayLoader.h b/samples/AnselSDKDelayLoader/source/DelayLoader.h new file mode 100644 index 0000000..216261b --- /dev/null +++ b/samples/AnselSDKDelayLoader/source/DelayLoader.h @@ -0,0 +1,41 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright 2016 NVIDIA Corporation. All rights reserved. + +#pragma once + +enum DelayLoadStatus +{ + kDelayLoadOk = 0, + kDelayLoadDllNotFound = -1, + kDelayLoadIncompatibleVersion = -2, +}; +// In order to use delay loading instead of regular linking to a dynamic library +// define ANSEL_SDK_DELAYLOAD for the project and use this function to explicitly +// load the library. If you don't specify a path then Win32 LoadLibrary search +// mechanism is applied. If you do specify a path it should be the full path to +// the AnselSDK32/64.dll in utf8 encoding. +DelayLoadStatus loadAnselSDKLibrary(const char* pathToLibraryUtf8 = nullptr); -- cgit v1.2.3