Name NV_clip_space_w_scaling Name Strings GL_NV_clip_space_w_scaling Contact Kedarnath Thangudu, NVIDIA Corporation (kthangudu 'at' nvidia.com) Contributors Eric Werness, NVIDIA Corporation Ingo Esser, NVIDIA Corporation Pat Brown, NVIDIA Corporation Mark Kilgard, NVIDIA Corporation Jason Schmidt, NVIDIA Corporation Status Shipping in NVIDIA release 367.XX drivers and up. Version Last Modified Date: November 25, 2017 Revision: 4 Number OpenGL Extension #486 OpenGL ES Extension #295 Dependencies This extension is written against OpenGL 4.5 Specification (Compatibility Profile). This extension interacts with the OpenGL ES 3.1 Specification. This extension requires NV_viewport_array2. If implemented in OpenGL ES, one of NV_viewport_array or OES_viewport_array is required. Overview 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 also 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 "w" coordinate of the vertices in the clip space before perspective divide. The clip space "w" coordinate of the vertices may be offset as of a function of "x" and "y" coordinates as follows: w' = w + Ax + By In the intended use case for viewport position scaling, an application should use a set of 4 viewports, one for each of the 4 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 A and B coefficients of the w-scaling equation above, that have the same value, but different signs, for each of the viewports. The signs of A and B should match the signs of X and Y for the quadrant that they represent such that the value of "w'" will always be greater than or equal to the original "w" value for the entire image. Since the offset to "w", (Ax + By), is always positive and increases with the absolute values of "x" and "y", the effective resolution will fall off linearly from the center of the image to its edges. New Procedures and Functions void ViewportPositionWScaleNV(uint index, float xcoeff, float ycoeff) New Tokens Accepted by the parameter of Enable, Disable, IsEnabled: VIEWPORT_POSITION_W_SCALE_NV 0x937C Accepted by the parameter of GetBooleani_v, GetDoublei_v, GetIntegeri_v, GetFloati_v, and GetInteger64i_v: VIEWPORT_POSITION_W_SCALE_X_COEFF_NV 0x937D VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV 0x937E Additions to Chapter 13 of the OpenGL 4.5 (Compatibility Profile) Specification (Fixed-Function Vertex Post-Processing) Modify Section 13.2 (Transform Feedback), p. 453 [section 12.1 in OpenGL ES] Modify the first paragraph: ...The vertices are fed back after vertex color clamping, but before viewport mask expansion, w coordinate warping, flat-shading, and clipping... Add a new Section 13.X (Viewport W Coordinate Scaling) If VIEWPORT_POSITION_W_SCALE_NV is enabled, the w coordinates for each primitive sent to a given viewport will be scaled as a function of its x and y coordinates using the following equation: w' = xcoeff * x + ycoeff * y + w; The coefficients for "x" and "y" used in the above equation depend on the viewport index, and are controlled by the command void ViewportPositionWScaleNV(uint index, float xcoeff, float ycoeff); The viewport specified by has its coefficients for "x" and "y" set to the and values. Specifying these coefficients enables rendering images at a non-uniform resolution, in particular a resolution that falls off linearly from the center towards the edges, which is useful for VR applications. 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. VR applications may use the w-scaling to minimize the processing of unused fragments. To achieve the intended effect, applications should use a set of 4 viewports one for each of the 4 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 the x and y coefficients of the w-scaling equation above, that have the same value, but different signs, for each of the viewports. The signs of and should match the signs of X and Y for the quadrant that they represent such that the value of "w'" will always be greater than or equal to the original "w" value for the entire image. Since the offset to "w", (Ax + By), is always positive and increases with the absolute values of "x" and "y", the effective resolution will fall off linearly from the center of the image to its edges. Errors: - The error INVALID_VALUE is generated if is greater than or equal to the value of MAX_VIEWPORTS. New Implementation Dependent State None. New State Initial Get Value Get Command Type Value Description Sec. Attribute ------------------------------------ ----------- ---- ------- ----------- ---- --------- VIEWPORT_POSITION_W_SCALE_NV IsEnabled B FALSE Enable W coordinate Scaling 13.X enable VIEWPORT_POSITION_W_SCALE_X_COEFF_NV GetFloati_v R 0 x coefficient for the w 13.X viewport coordinate scaling equation VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV GetFloati_v R 0 y coefficient for the w 13.X viewport coordinate scaling equation Additions to the AGL/GLX/WGL/EGL Specifications None. GLX Protocol None. Errors None. Interactions with OpenGL ES 3.1 If implemented in OpenGL ES, remove all references to GetDoublei_v. If NV_viewport_array is supported, replace all references to MAX_VIEWPORTS and GetFloati_v with MAX_VIEWPORTS_NV and GetFloati_vNV respectively. If OES_viewport_array is supported, replace all references to MAX_VIEWPORTS and GetFloati_v with MAX_VIEWPORTS_OES and GetFloati_vOES respectively. Issues (1) Does this extension provide any functionality to convert the w-scaled image to the barrel distorted image used in VR? RESOLVED: No. VR applications would still require a post-processing step to generate a barrel distorted image to compensate for the lens distortion. The following vertex and fragment shader pair un-warps a w-scaled image. It can be incorporated into an existing post-processing shader to directly convert a w-scaled image to the barrel distorted image. // 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); } (2) In the standard use case a application sets up 4 viewports, one for each quadrant. Does each primitive have to be broadcast to all the 4 viewports? RESOLVED: No. Applications may see a better performance if the viewport mask for each primitive is limited to the viewports corresponding to the quadrants it falls in. Revision History Revision 1 - Internal revisions. Revision 2 - Add _NV suffixes to _COEFF tokens Revision 3 - Add ES interactions. - Add requirement for NV_viewport_array2 Revision 4, 2017/11/25 (pbrown) - Add to the OpenGL ES Extension Registry