Computer Graphics Rendering Basics

Last update: 2021-07-31 18:25:07 +0800 +0800
tags: Graphics | Webgl | Gpu
Available translations: 日本語 / 中文(简体) / 中文(繁體)

Rendering turns abstract geometry into pixels. A GPU pipeline takes vertices, transforms them, clips them, rasterizes the visible shapes, and shades the resulting fragments.

The Pipeline #

A typical rendering pipeline has these stages:

  1. vertex processing;
  2. primitive assembly;
  3. clipping and viewport transform;
  4. rasterization;
  5. fragment shading;
  6. depth and blending;
  7. frame-buffer writeback.

That sequence matters because each stage narrows the problem from geometry to pixels.

Vertex Data #

The input usually starts as a list of vertices and an index buffer.

  • vertices contain positions and optional attributes such as color, normal, or texture coordinates;
  • indices reuse vertices across triangles;
  • primitives are usually triangles because triangles are always planar.

The vertex shader runs once per vertex. Its job is to transform positions into clip space and to pass per-vertex data downstream. A conventional transform multiplies each object-space position by model, view, and projection matrices:

text
clip_position = projection * view * model * object_position

The model matrix places an object in world space, the view matrix expresses that world relative to the camera, and the projection matrix maps the camera-space frustum into homogeneous clip space. Matrix order depends on the API and vector convention; the shader and host code must agree.

Clip Space and Clipping #

Geometry outside clip space is clipped before rasterization. In OpenGL and WebGL, a clip-space vertex is inside when -w <= x, y, z <= w. If a triangle crosses a boundary, the GPU creates the visible polygon and discards the outside portion.

After clipping, perspective division computes normalized device coordinates (NDC) as (x/w, y/w, z/w). The viewport transform then maps NDC to window coordinates. Interpolation for perspective-dependent attributes uses the homogeneous w values so texture coordinates do not distort as if they were affine screen-space values.

Rasterization #

Rasterization converts a triangle into fragments, which are candidate pixels. The rasterizer decides which sample locations lie inside the triangle and interpolates attributes across the surface.

Interpolated values include:

  • color;
  • depth;
  • texture coordinates;
  • normals or other varyings.

This interpolation is why a gradient can appear across a triangle even though the input only specified values at the corners.

Fragment Shading #

The fragment shader runs once per fragment and computes the final color or discard decision.

Typical fragment work includes:

  • texture sampling;
  • lighting approximation;
  • alpha testing or discard;
  • color correction;
  • procedural patterns.

This stage is where many visually important effects happen, because the shader can combine interpolated attributes with textures and uniforms.

Depth, Blending, and Framebuffers #

The depth buffer resolves visibility between overlapping primitives. If one fragment is closer than another, the closer one usually wins.

Blending combines source and destination colors for translucent surfaces. It is useful for transparency, particles, and UI effects, but it depends on draw order. Opaque geometry is commonly drawn first with depth writes enabled, followed by back-to-front translucent geometry with carefully selected blend factors.

The final color lands in the frame buffer, which is then presented to the screen or to an image target.

WebGL View #

WebGL exposes this pipeline through JavaScript. A canvas provides the drawing surface, shaders are supplied as source strings, and the browser hands the work to the GPU. WebGL inherits OpenGL ES clip-space conventions: NDC spans [-1, 1] on all three axes, while window coordinates place the viewport origin at the lower left. Browser image sources often appear top-down, so texture upload or coordinates may require an explicit vertical flip.

The mental model is still the same:

  • upload buffers;
  • configure vertex attributes;
  • compile shaders;
  • bind a program, framebuffer, and other required state;
  • draw triangles;
  • present the resulting frame.

Practical Rule #

WebGL is a state machine. A draw call consumes the currently bound program, vertex-array and buffer bindings, textures, framebuffer, viewport, depth state, and blend state. When output is wrong, inspect that complete state at the draw call rather than only the shader source.

Comments

Read or comment on GitHub (sign-in required to comment)