Vulkan-Docs/appendices/VK_NV_clip_space_w_scaling.txt
Jon Leech 279452463a Change log for November 12, 2018 Vulkan 1.1.92 spec update:
* Update release number to 92.

Public Issues:

  * Move and modify valid usage statements dealing with pname:aspectMask in
    flink:vkCmdClearColorImage, flink:vkCmdClearDepthStencilImage, and
    slink:VkClearAttachment, so they are in places where all necessary
    information is available (public issue 529).
  * Fix math markup in <<textures-texel-anisotropic-filtering, Texel
    Anisotropic Filtering>> (public pull request 840).
  * Fix misspellings (public pull request 845).

Internal Issues:

  * Add installation instructions and a Makefile "`chunked`" target for
    chunked HTML generation (internal issue 1352).
  * Fix pipeline mesh diagram style; also fix a minor bug in the classic
    pipeline diagram where vertex/index buffers wrongly fed into the vertex
    shader (internal issue 1436).
  * Make asciidoctor ERROR output raise an error, and don't suppress
    executed command output from CI make invocation (internal issue 1454).
  * Minor typo fixes and clarifications for `VK_NV_raytracing`.
  * Cleanup extension-specific properties
  ** Remove duplicated documentation for pname:maxDiscardRectangles,
     pname:pointClippingBehavior, and pname:maxVertexAttribDivisor (they
     shouldn't be documented with the other members of
     slink:VkPhysicalDeviceLimits at all).
  ** Remove duplicate anchor for pname:maxVertexAttribDivisor
  ** Consistently document stext:VkPhysicalDevice<Extension>PropertiesKHR
  *** Always document pname:sType/pname:pNext (was inconsistent before)
  *** Always mention chaining to slink:VkPhysicalDeviceProperties2 (and not
      as slink:VkPhysicalDeviceProperties2KHR)
  *** Always include Valid Usage statements last
  * Update Makefile 'checklinks' target and associated scripts, and fix
    markup problems identified by checkLinks.py, so that we can rely on the
    checklinks script as part of Gitlab CI.
2018-11-12 04:40:40 -08:00

171 lines
5.1 KiB
Plaintext

include::meta/VK_NV_clip_space_w_scaling.txt[]
*Last Modified Date*::
2017-02-15
*Contributors*::
- Eric Werness, NVIDIA
- Kedarnath Thangudu, NVIDIA
Virtual Reality (VR) applications often involve a post-processing step to
apply a "`barrel`" distortion to the rendered image to correct the
"`pincushion`" distortion introduced by the optics in a VR device.
The barrel distorted image has lower resolution along the edges compared to
the center.
Since the original image is rendered at high resolution, which is uniform
across the complete image, a lot of pixels towards the edges do not make it
to the final post-processed image.
This extension provides a mechanism to render VR scenes at a non-uniform
resolution, in particular a resolution that falls linearly from the center
towards the edges.
This is achieved by scaling the [eq]#w# coordinate of the vertices in the
clip space before perspective divide.
The clip space [eq]#w# coordinate of the vertices can: be offset as of a
function of [eq]#x# and [eq]#y# coordinates as follows:
[eq]#w' = w + Ax + By#
In the intended use case for viewport position scaling, an application
should use a set of four viewports, one for each of the four quadrants of a
Cartesian coordinate system.
Each viewport is set to the dimension of the image, but is scissored to the
quadrant it represents.
The application should specify [eq]#A# and [eq]#B# coefficients of the
[eq]#w#-scaling equation above, that have the same value, but different
signs, for each of the viewports.
The signs of [eq]#A# and [eq]#B# should match the signs of [eq]#x# and
[eq]#y# for the quadrant that they represent such that the value of [eq]#w'#
will always be greater than or equal to the original [eq]#w# value for the
entire image.
Since the offset to [eq]#w#, ([eq]#Ax + By#), is always positive, and
increases with the absolute values of [eq]#x# and [eq]#y#, the effective
resolution will fall off linearly from the center of the image to its edges.
=== New Object Types
None.
=== New Enum Constants
* Extending elink:VkStructureType:
** ename:VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV
* Extending elink:VkDynamicState:
** ename:VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV
=== New Enums
None.
=== New Structures
* slink:VkViewportWScalingNV
* slink:VkPipelineViewportWScalingStateCreateInfoNV
=== New Functions
* flink:vkCmdSetViewportWScalingNV
=== Issues
1) Is the pipeline struct name too long?
*RESOLVED*: It fits with the naming convention.
2) Separate W scaling section or fold into coordinate transformations?
*RESOLVED*: Leaving it as its own section for now.
=== Examples
[source,c++]
--------------------------------------
VkViewport viewports[4];
VkRect2D scissors[4];
VkViewportWScalingNV scalings[4];
for (int i = 0; i < 4; i++) {
int x = (i & 2) ? 0 : currentWindowWidth / 2;
int y = (i & 1) ? 0 : currentWindowHeight / 2;
viewports[i].x = 0;
viewports[i].y = 0;
viewports[i].width = currentWindowWidth;
viewports[i].height = currentWindowHeight;
viewports[i].minDepth = 0.0f;
viewports[i].maxDepth = 1.0f;
scissors[i].offset.x = x;
scissors[i].offset.y = y;
scissors[i].extent.width = currentWindowWidth/2;
scissors[i].extent.height = currentWindowHeight/2;
const float factor = 0.15;
scalings[i].xcoeff = ((i & 2) ? -1.0 : 1.0) * factor;
scalings[i].ycoeff = ((i & 1) ? -1.0 : 1.0) * factor;
}
VkPipelineViewportWScalingStateCreateInfoNV vpWScalingStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV };
vpWScalingStateInfo.viewportWScalingEnable = VK_TRUE;
vpWScalingStateInfo.viewportCount = 4;
vpWScalingStateInfo.pViewportWScalings = &scalings[0];
VkPipelineViewportStateCreateInfo vpStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
vpStateInfo.viewportCount = 4;
vpStateInfo.pViewports = &viewports[0];
vpStateInfo.scissorCount = 4;
vpStateInfo.pScissors = &scissors[0];
vpStateInfo.pNext = &vpWScalingStateInfo;
--------------------------------------
Example shader to read from a w-scaled texture:
[source,c++]
--------------------------------------
// Vertex Shader
// Draw a triangle that covers the whole screen
const vec4 positions[3] = vec4[3](vec4(-1, -1, 0, 1),
vec4( 3, -1, 0, 1),
vec4(-1, 3, 0, 1));
out vec2 uv;
void main()
{
vec4 pos = positions[ gl_VertexID ];
gl_Position = pos;
uv = pos.xy;
}
// Fragment Shader
uniform sampler2D tex;
uniform float xcoeff;
uniform float ycoeff;
out vec4 Color;
in vec2 uv;
void main()
{
// Handle uv as if upper right quadrant
vec2 uvabs = abs(uv);
// unscale: transform w-scaled image into an unscaled image
// scale: transform unscaled image int a w-scaled image
float unscale = 1.0 / (1 + xcoeff * uvabs.x + xcoeff * uvabs.y);
//float scale = 1.0 / (1 - xcoeff * uvabs.x - xcoeff * uvabs.y);
vec2 P = vec2(unscale * uvabs.x, unscale * uvabs.y);
// Go back to the right quadrant
P *= sign(uv);
Color = texture(tex, P * 0.5 + 0.5);
}
--------------------------------------
=== Version History
* Revision 1, 2017-02-15 (Eric Werness)
- Internal revisions