skia / external / github.com / KhronosGroup / OpenGL-Registry / refs/heads/11723-workgroup / . / extensions / NV / NV_clip_space_w_scaling.txt

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 <cap> parameter of Enable, Disable, IsEnabled: | |

VIEWPORT_POSITION_W_SCALE_NV 0x937C | |

Accepted by the <pname> 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 <index> has its coefficients for "x" and "y" | |

set to the <xcoeff> and <ycoeff> 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 | |

<xcoeff> and <ycoeff> 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 <index> 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 |