420 likes | 503 Views
Basic Rendering. CS 4363/6353. The Graphics Pipeline Overview. Vertex Processing Coordinate transformations Compute color for each vertex Clipping and Primitive Assembly Assemble sets of vertices into lines and polygons
E N D
Basic Rendering CS 4363/6353
The Graphics Pipeline Overview • Vertex Processing • Coordinate transformations • Compute color for each vertex • Clipping and Primitive Assembly • Assemble sets of vertices into lines and polygons • Clipping volume culls out geometry outside, and clips geo that straddles • Rasterization • Determine which pixels are inside each polygon (primitive) • The output is a set of fragments for each primitive • Fragment Processing • Fills in the pixels in the frame buffer (what you’re seeing right now!)
Shaders(from 100,000 feet. Well, maybe 10,000 feet) • Shaders: • Expose the programmable pipeline ! • Allow us to manipulate vertices and pixel colors • Look very similar to C • void main() • Must be compiled and linked from source • Generally have two shaders: • Vertex shader (to handle vertex transformations and lighting) • Fragment shaders (to handle per-pixel operations like lighting to determine color) • Hundreds (or thousands) of GPUs are available
Shaders and Passing Data • Must feed shaders some data! Three ways to pass. • Attributes (vertex shaders only): • data that changes per vertex • A four component vector (regardless if you use it or not) • Copied from your OpenGL program into a buffer • Uniforms (vertex/fragment shaders): • A single value that is shared for all attributes • Common for transformation matrices (vertex shader) • Texture (mostly fragment shaders): • Used for texture data
Simple Vertex Example #version 150 in vec4 vPosition; // This data is from your OpenGL code void main () { gl_Position = vPosition; }
Simple Fragment Shader #version 150 out vec4 fColor; void main () { fColor = vec4(1.0, 0.0, 0.0, 1.0); } // Hard-coded red!
Shaders and Passing Data • outs/ins • Used for passing data between shaders • Client (OpenGL code) has no access to these variables • Vertex shader’sout variable corresponds to the fragment shader’sin variable.
Rendering Options • We typically create a single batch of vertices to draw • We generally set up all “features” before drawing anything • State machine mentality • We always have vertices, but we can render them in 7 different ways • GL_POINTS • GL_LINES • GL_LINE_STRIP • GL_LINE_LOOP • GL_TRIANGLES** • GL_TRIANGLE_STRIP • GL_TRIANGLE_FAN
Rendering Options(GL_POINTS) • Can change the point sizes, but not important right now • Points are always square unless anti-aliased
Rendering Options(GL_LINES) • Connects in pairs (line segments), so should have an even number of points • Change line width with glLineWidth (GLfloat width);
Rendering Options(GL_LINE_STRIP) • In a connect-the-dots fashion, draw from one vertex to another • How would you do this with GL_LINES?
Rendering Options(GL_LINE_LOOP) • Closes the loop • Is typically what you would use for outlines/tracing
Rendering Options(OTHERS) • Some of these are allowed…
Rendering Options(OTHERS) • Some of these aren’t… • NO QUADS! Triangles only…
Triangle Winding V1 • Simply means the order of the vertices you specify • Clockwise • Counter-Clockwise • Why is this important? • Clockwise is back facing • Counter-clockwise is front facing • Long story short: • If you specify in reverse order, sometimes you won’t see anythingor it will be reversed • Can reverse using glFrontFace (GL_CW); V0 V2 V2 V0 V1
Triangle Strips • Specify the first triangle (V0, V1, V2) V2 V0 V1
Triangle Strips • Specify the first triangle (V0, V1, V2) • The next vertex (V3) creates a new triangle (V1, V2, V3) V2 V3 V0 V1
Triangle Strips • Specify the first triangle (V0, V1, V2) • The next vertex (V3) creates a new triangle (V1, V2, V3) • The next vertex (V4) creates a new triangle (V2, V3, V4) V4 V2 V3 V0 V1
Example • From Wikipedia…
Triangle Fans • Can create a fan where V0 is the central vertex • Specify first triangle, then each new vertex is a wedge of the fan V2 V0 V1
Triangle Fans • Can create a fan where V0 is the central vertex • Specify first triangle, then each new vertex is a wedge of the fan • Still uses V0 V3 V2 V0 V1
Triangle Fans • Can create a fan where V0 is the central vertex • Specify first triangle, then each new vertex is a wedge of the fan • Still uses V0 V3 V2 V4 V0 V1
Culling and Depth Testing • You’re going to be drawing a lot of triangles • What happens if you draw one triangle on top of another? • What if the second triangle is far away? • Sort triangles of an object (painter’s algorithm)? • What about several objects on the screen? • Also, should you be able to see the inside of geometry? • Basically, there are two problems: • Unseen triangles are unlit • The depth of the triangles is important
Houston, we have a problem(Image from OpenGL SuperBible) • Sometimes rendering the far-side triangles (which are unlit)
Backface Culling • Simply means “Don’t draw triangles that don’t face the camera” • Two steps in OpenGL • glEnable (GL_CULL_FACE); • glCullFace (GL_BACK); • glCullFace could also use: • GL_FRONT • GL_FRONT_AND_BACK
Culling the Backface(s) • Problem solved?
Depth Testing • Just because we culled the back-facing triangles doesn’t mean they’re sorted! • Depth testing: • Removes hidden surfaces • Each pixel has a depth (z-value) • Higher values mean closer to the camera • This value is stored in the depth buffer • glEnable (GL_DEPTH_TEST); • Is this starting to make sense? glutInitDisplayMode (GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);
Polygon Rendering Modes • Polygons do not have to be filled • We have 3 modes to draw polygons: • GL_FILL – what we’ve been using • GL_LINE – 3D wireframe • GL_POINT – just the vertices • Call glPolygonMode() to change rendering value: // renders front and back facing polys in wireframe glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
GL_LINE • Backface culling and depth testing are turned on
A Note about Polygon Offset • You can skip it • Sometimes draw two triangle very close to the same depth (called decaling) • This creates “z-fighting” • Part of the further polygon shows • Before rendering closer triangle: glEnable (GL_POLYGON_OFFSET_LINE); glPolygonOffset(-1.0f, -1.0f);
Scissor Test • We won’t be using this in our code, but: • Used to increase performance • Updates only the portion within a defined area(i.e. doesn’t update anything outside of that area) • By default, scissor test is the size of the window • Use glScissor (int x, int y, int width, int height): glEnable (GL_SCISSOR_TEST); glScissor (100, 100, 600, 400); // only render in that area
Blending • Without depth testing, color values overwrite one another • With depth testing, new fragments may replace old ones • Discards further fragments • This no longer happens with OpenGL blending: glEnable (GL_BLENDING); • Remember, each color has a red, green, blue and alpha!
Specifying How to Blend • We must specify how the blending occurs • Destination color is the color already in the color buffer • Source color is the one we’re about to write into the color buffer Cf = (Cs * S) + (Cd * D) • Where: • Cf is the final color, Cs is the source color and Cd is the destination color • S is the source blending factor • D is the destination blending factor
Most Common Method • glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); • Take source and multiply rgb (colors) by its alpha value • Take destination and multiply rgb by (1-source alpha) • Example: • Cd = (1.0f, 0.0f, 0.0f, 1.0f) //Red • Cs = (0.0f, 0.0f, 1.0f, 0.6f) // Blue, with source alpha 0.6 • D = 1.0f – 0.6 == 0.4f • Cf = (Blue*0.6) + (Red*0.4)
One final Note • We can change the underlying equation as well using glBlendEquation(): • GL_FUNC_ADDCf = (Cs*S)+(Cd*D) • GL_FUNC_SUBTRACTCf= (Cs*S)-(Cd*D) • GL_FUNC_REVERSE_SUBTRACTCf= (Cd*D) - (Cs*S) • GL_MINCf= min(Cs,Cd) • GL_MAXCf = max(Cs,Cd)
Antialiasing • We have square pixels, which make the image look computer-generated • The visual aspect of this is called “the jaggies” • To eliminate, OpenGL uses blending of source with surrounding destination pixels • So: glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); • Then: glEnable(GL_POINT_SMOOTH); // and/or glEnable (GL_LINE_SMOOTH); // and/or glEnable (GL_POYGON_SMOOTH); // ** // ** outdated or not supported at all!
Multisampling • Helps to smooth out polygons • Creates another buffer (color, depth and stencil) • All primitives are sampled multiple times, then “averaged” • You take a performance hit here, but looks good! • Point/Line antialiasing is disable when multisampling is enabled • First: glutInitDisplayMode (GLUT_DOUBLE| GLUT_RGB| GLUT_DEPTH| GLUT_MULTISAMPLE); • Then: glEnable (GL_MULTISAMPLE);