Posted on

Table of Contents

Shading Frequencies

Flat Shading

In flat shading, we can calculate normal vector and shading per triangle faces. However, this is not good for smooth surfaces.

flatshading

Gouraud shading

Also we can calculate the normal vector for each vertices, and interpolate across triangle.

gouraudshading

How could we calculate the vertices normal?

averagenormal

We can use the average of surrounding faces normal. Nv=iNiNi N_v = \frac{\sum_i \textbf{N}_i}{||\textbf{N}_i||}

Phong shading

We can also calculate each pixel's normal vector across triangles.

phongshading

How can we define the normal of each pixel?

Still we can use interpolation:

interpolationnormal

Graphics Pipline

graphics-pipeline

  1. Input: vertices
  2. Vertices positioned in screen space (MVP Transforms;Gouraud Shading with Vertex Shader)
  3. Triangles positioned in screen space
  4. Fragments (Rasterization; Antialiasing)
  5. Shaded fragments (Z-Buffer Test;Phong Shading with Fragment Shader)
  6. Output: Image

Shader

We can write a universal program on Graphic Hardware's to process shading, we call it shader, e.g. OpenGL Shading Lang (GLSL).

Texture Mapping

In shading, we may want to put some texture on object. In the texture, it defines the kd,ks,kak_d,k_s,k_a and some other important properties.

Surface

First, we need to define the target of mapping, surface. We can consider the surface is 2D. So, our texture can be a 2D Image.

In mathematics, it is called Parameterization, which is rather complex, so we can assume the mapping is already down by hand or some other programs.

Texture Coordinate

With parameterization, we can map each vertex into texture image coordinate(u,v) in [0,1]2[0,1]^2

UV

We can also use a texture image multiple times, however, we may want to make the texture tiled!

Texture Magnification

If the texture is too small we can do image interpolation.

interpolation

  • (a) Nearest
  • (b) Bilinear
  • (c) Bicubic
  • (d) Original

interpolationcompare

Bilinear Interpolation

f(x,y)=1(x1x0)(y1y0)[x1xxx0][f(x0,y0)f(x0,y1)f(x1,y0)f(x1,y1)][y1yyy0] f(x,y) = \frac{1}{(x_1-x_0)(y_1-y_0)} \begin{bmatrix} x_1-x & x - x_0 \end{bmatrix} \begin{bmatrix} f(x_0,y_0) & f(x_0,y_1) \cr f(x_1,y_0) & f(x_1,y_1) \cr \end{bmatrix} \begin{bmatrix} y_1-y \cr y-y_0 \end{bmatrix}

Texture minification

If the texture is too large, simply down-sampling will cause Moiré Effect (aliasing).

Of cause we can do super sampling, but it's costly. Sometimes we need to use super high sampling frequency for each pixel.

A simple way is just use the average value within a range.

Mipmap

Mipmap allow us to do fast, approximate, square range queries.

mipmaps

We can pre-generate different level of original texture, for each layer, the size is half-down average. We only need extra 1/3 storage overhead.

uvinterp

The area of a pixel in texture we can use simplified finite difference: D=log2L D = \log_2{L}

L=max((dudx)2+(dvdx)2,(dudy)2+(dvdy)2) L = \max(\sqrt{(\frac{du}{dx})^2+(\frac{dv}{dx})^2},\sqrt{(\frac{du}{dy})^2+(\frac{dv}{dy})^2})

Where DD​ is the level in mipmap.

Over the mipmap, we can use trilinear interpolation:

minimapinterp

Anisotropic Filtering

However, mipmap may cause over blur.

Anisotropic ripmaps can maintain one-dimension information during down-sampling instead of losing both dimension qualities.

ripmap

When querying for triangular part, this will improve the accuracy than return an average of square texture.

The overhead of ripmap is 300%.

Barycentric Coordinates

We can use barycentric coordinates to get the value inside a triangle based on vertices.

barycentric (x,y)=p0(x0,y0)+p1(x1,y1)+p2(x2,y2) (x,y) = p_0(x_0,y_0) + p_1(x_1,y_1) + p_2(x_2,y_2)

p0+p1+p2=1 p_0 + p_1 + p_2 = 1

For any point inside triangle, we can use a linear formation of three vertices.

If p0,p1,p2>0p_0,p_1,p_2 > 0​, this point must inside the triangle.

The coordinates are the ratio of the smaller triangle' area to entire triangle's area. p0=A0A0+A1+A2 p_0 = \frac{A_0}{A_0+A_1+A_2}

p1=A1A0+A1+A2 p_1 = \frac{A_1}{A_0+A_1+A_2}

p2=A2A0+A1+A2 p_2 = \frac{A_2}{A_0+A_1+A_2}

Also a simplified way by cross product: p0=(xx1)(y2y1)+(yy1)(x2x1)(x0x1)(y2y1)+(y0y1)(x2x1) p_0 = \frac{-(x-x_1)(y_2-y_1)+(y-y_1)(x_2-x_1)}{-(x_0-x_1)(y_2-y_1)+(y_0-y_1)(x_2-x_1)}

p1=(xx2)(y0y2)+(yy2)(x0x2)(x1x2)(y0y2)+(y1y2)(x0x2) p_1 = \frac{-(x-x_2)(y_0-y_2)+(y-y_2)(x_0-x_2)}{-(x_1-x_2)(y_0-y_2)+(y_1-y_2)(x_0-x_2)}

p2=1p0p1 p_2 = 1 - p_0 - p_1

So for a property VV inside triangle (like position, texture, color, normal, depth, etc.), we can use barycentric coordinates to interpolate. V=p0V0+p1V1+p2V2 V = p_0V_0+p_1V_1 + p_2V_2 However, the barycentric coordinates are not invariant under projection.