02.06.2013 Views

S0611-GTC2012-Edge-Ware-Shaders

S0611-GTC2012-Edge-Ware-Shaders

S0611-GTC2012-Edge-Ware-Shaders

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Edge</strong>-Aware <strong>Shaders</strong><br />

Peter-Pike Sloan and Peter Shirley<br />

NVIDIA


Motivation


Conventional shaders unaware of edges<br />

P


Conventional shaders unaware of edges<br />

P<br />

a


Inspiration PLACEHOLDER - PERMISSIONS<br />

Z N RGB<br />

[Deering88]<br />

[Reshetov09]<br />

[FXAA10]<br />

[Nehab07]


Alternative approaches?<br />

Explicitly model geometry/texture?<br />

— Increases authoring time and storage<br />

— Concave edges implicitly defined<br />

Completely in CUDA/DXCompute?<br />

— Rasterization turns out to be useful<br />

Forward rendering?<br />

— Implicit features<br />

— Conceptually clean in deferred<br />

[Kavan11]


Why not use CUDA or DirectCompute?<br />

Rasterization<br />

— Splatting convex edges, splatting corners<br />

Setup Draw Call parameters from GPU<br />

— Also in DirectCompute<br />

A (tiny) bit easier to integrate with graphics app<br />

RWStructuredBuffer WSCornerBuffer;<br />

uint uPos = WSCornerBuffer.IncrementCounter();<br />

WSCornerBufferRead[uPos].Color = float3(1,0,0);<br />

pd3dDeviceContext->CopyStructureCount(pCountBuffer,4,m_WSCornerBufferUAV);<br />

pd3dDeviceContext->DrawIndexedInstancedIndirect(pCountBuffer,0);


Algorithm<br />

Splat convex edges<br />

Search GBuffer for edges<br />

Flood Fill (jump flooding)<br />

Splat existing corners<br />

Search for new corners<br />

Update GBuffer<br />

Shade image


<strong>Edge</strong> Features


Line Information + Feature Buffer<br />

Direction vector in eye space<br />

Point on edge [*]<br />

Feature buffer<br />

— asfloat(distance)<br />

— 2x12bits for location<br />

— 1 bit concave/convex<br />

— 2 bits for which neighbor<br />

2x32 bits uint<br />

2x16 bits SNORM [Meyer10]<br />

4x32 bits float


Silhouette <strong>Edge</strong>s<br />

struct AuxFace {<br />

unsigned int uFlags; // 3 bits edge info, 24 bits are material ID's<br />

float3 OppNormals[3]; // opposite normals<br />

};<br />

StructuredBuffer SilAuxFaceBuffer;


Silhouette <strong>Edge</strong>s<br />

// now fixup these distances<br />

[branch]<br />

if (fDist.x < g_DistanceThreshold) {<br />

float fCheck = dot(P-verts[0],edgeVectors[0]);<br />

if (fCheck < 0) {<br />

fDist.x = length(P-verts[0]);<br />

} else if (fCheck > dot(edgeVectors[0],edgeVectors[0])) {<br />

fDist.x = length(P-verts[1]);<br />

}<br />

}


Line Textures (sparse)


Flood Fill<br />

Jump Flooding<br />

[Rong06]


Flood Fill


Corners


Corner Search<br />

First Pass<br />

— Volume of neighboring normals:<br />

— Store distance, set candidate bit, encode neighbor<br />

Second Pass<br />

(abs(dot(N,cross(NR,ND))) > 0.2f)<br />

— Suppress corner if any 8-connected neighbor is closer<br />

struct WSCornerStruct {<br />

float3 CornerPos; // origin<br />

float3 CornerNorm; // average normal at corner<br />

float3 LineDirs[3]; // direction for each edge<br />

float3 LineNorms[3]; // needed for shading – average of faces<br />

uint LineInfo[3]; // has convex/concave bit, material pair 17 bits only...<br />

};<br />

RWStructuredBuffer WSCornerBufferWrite; // IncrementCounter() to add<br />

StructuredBuffer WSCornerBufferRead;


Corner Splat<br />

Occurs before search<br />

Copy the number of corners into CountBuffer (GPU)<br />

Transform corners into eye space (CountBuffer+PS)<br />

Draw a cube for each corner, # Instances from CountBuffer<br />

pd3dDeviceContext->CopyStructureCount(pCountBuffer,4,m_WSCornerBufferUAV);<br />

// Bunch of other code…<br />

pd3dDeviceContext->DrawIndexedInstancedIndirect(pCountBuffer,0);<br />

Bit in Feature Buffer set indicating corner<br />

— Screen coordinates replaced with corner ID, neighbor replaced<br />

with edge index in corner buffer


Corner Fixup


Results


Original


Modify G-Buffer<br />

Round edges – interpolate to average normal at edge<br />

Paint slop – use material ID on either side + noise<br />

Grout/Caulk – material ID on either side


Performance Quadro 5000<br />

Task ms %<br />

Compute G Buffer 882 8.78<br />

Line Buffers (splat + search) 1360 13.53<br />

Jump Flooding 6670 66.36<br />

Corner splat + search 508 5.05<br />

Shade 631 6.28


Future Work<br />

Performance<br />

— Faster Jump Flooding [Rong2007]<br />

— Compress Buffers<br />

— Move stages to compute/CUDA?<br />

Quality<br />

— Interaction with FXAA? AA in general?<br />

— LOD<br />

Workflow/artist in the loop?


References<br />

[Deering88] The Triangle Processor and Normal Vector Shader: a VLSI System<br />

for High Performance Graphics, SIGGRAPH 1998<br />

[Reshetov09] Morphological Antialiasing, HPG 2009<br />

[FXAA10]<br />

http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_<br />

WhitePaper.pdf<br />

[Nehab07] Accelerating Real-Time Shading with Reverse Reprojection<br />

Caching, Graphics Hardware 2007<br />

[Kavan11] Least Squares Vertex Baking, EGSR 2011<br />

[Meyer10] On floating-point normal vectors, EGSR 2010<br />

[Rong06] Jump Flooding in GPU with Applications to Voronoi Diagram and<br />

Distance Transform, I3D 2006<br />

[Rong07] Variants of Jump Flooding Algorithm for Computing Discrete Voronoi<br />

Diagrams, 4 th Symposium on Voronoi Diagrams in Science and Engineering


Backup slides after this…


Line Features


Line textures (sparse set of points)


Flood Fill


Flood Fill

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!