Texture Mapping:用图片或者pattern提供像素的颜色,有1d, 2d, 3d, 4d纹理
Environment Mapping:用物体周围的环境作为纹理
Bump Mapping:用来在着色时扰动法向量
Texture Space
通常是二维图片空间[0,1]×[0,1]
纹理坐标(u, v)或者(s, t)
每个顶点设置对应的纹理坐标
Texture Mapping
三维World space到二维Texture space的一个映射,增加真实效果同时不提高模型复杂度。
思路:
网格顶点(x, y, z )映射到纹理坐标(u, v)保角映射,等面积映射,等距映射
图元的纹理坐标在屏幕空间用重心坐标插值
读取(u, v)对应的纹理颜色,作为漫反射系数KdK_dKd
Texture Mapping in OpenGL
基本流程:
- 启用纹理功能
- 创建纹理对象
- 绑定纹理(状态)
- 读图文件或者生成纹理图案
- 设置纹理参数
- Wrapping
- Filtering
- Mipmapping
- 对每个顶点设置纹理坐标
在流程中需要的地方启用纹理,一般是display回调函数里
glEnable(GL_TEXTURE_2D)
DrawObject()…
glDisable(GL_TEXTURE_2D)
创建和绑定纹理对象(OpenGL状态)
GLuint handles[2];
glGenTextures(2, handles);//生成texture ID 或names
//绑定第一个纹理ID为当前纹理
glBindTexture(GL_TEXTURE_2D, handles[0]);
…
//可以对不同的物体,切换到另一个纹理ID
glBindTexture(GL_TEXTURE_2D, handles[1]);
设置纹理环境参数(纹理贴图和材质颜色的计算方式)
glTexEnv{fi}[v](GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param)
混合模式param:
- 默认GL_MODULATE:j结合光照和纹理(乘积,纹理作为物体材质)
- GL_DECAL:只采用纹理的颜色(如果透明,会混合物体的颜色)
- GL_REPLACE:只采用纹理的颜色(包括透明度)
- GL_BLEND:混合周围的颜色(GL_TEXTURE_ENV_COLOR)
- GL_ADD:物体的颜色加上纹理颜色
Specify Texture Image
生成棋盘纹理
- Glubyte check_board[64][64]
- 离散采点:
&:按位与,在这里的效果是每隔8位,i&8==0的值变一次
实现棋盘格纹理
读取图片数据
- ppm:可移植像素格式,按格式读取文本
- jpg(stb_image.h):
- 使用stbi_load()读取JPG图片
- 使用stbi_image_free()释放jpg缓存
棋盘纹理
用数学公式生成复杂的棋盘纹理
用数学公式生成复杂棋盘纹理
对当前纹理对象设置图片数据
调用glTexImage2D(target, level, components, w, h, border, fromat, type. texels)
- target: GL_TEXTURE_2D
- level: mipmap level
- components: 纹理颜色通道数
- w, h: 纹理的宽高
- border: used for smoothing
- format and type: 纹理数据格式
- texels: 纹理数据
OpenGL纹理的尺寸要求是2的指数次方
对于图文件,可以转换 - gluScaleImage(format, w_in, h_in, type_in, *data_in, w_out, h_out, type_out, *data_out);
透视纠正
纹理坐标使用重心坐标插值设置内部像素纹理,在透视后会出现扭曲
透视纠正的深度插值:
设置当前纹理参数
设置纹理映射的参数
Texture Wrapping(超出纹理坐标标准范围时)
- GL_TEXTURE_WRAP_S: S轴方向
- GL_TEXTURE_WRAP_T: T轴方向
如果纹理坐标超出[0, 1]
- 默认GL_REPEAT, 重复贴图
- 设置GL_CLAMP,截断
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
Repeating = (s%1, t%1) - GL_REPEAT
- GL_MORRORED_REPEAT每次重复沿着一个轴镜像翻转
Clamping = (min(s/t, 1), max(s/t, 0))
- GL_CLAMP
- GL_CLAMP_TO_EDGE
- GL_CLAMP_TO_BORDER
Texture Filtering(纹理采样的策略)
- GL_TEXTURE_MAG_FILTER
- GL_TEXTURE_MIN_FILTER
纹理坐标可以是任意浮点数,不依赖图片的分辨率(width,height)
纹理采样的两种情况:
-
三角形覆盖像素比对应纹理元素要多:比如图片分辨率很低。需要一个纹理元素对应到多个屏幕像素(放大)
-
三角形覆盖像素比对应纹理元素要少:比如三角形在远处。需要多个纹理元素对应同一个屏幕像素(缩小)
Mipmap(多级渐远纹理,消除摩尔纹失真)
**Magnification:**一个纹理对应多个屏幕像素
**Minification:**多个纹理点对应一个屏幕像素
采样(最近点,线性插值)解决
Magnification
纹理过小,多个屏幕点对应一个纹理点
- 最近原则(Nearest)
- 双线性插值(Bilinear Interpolation)
Minification
纹理过大:多个纹理点对应一个屏幕点
容易导致更严重的走样
纹理参数的设置
调用glTexParameteri(target, type, mode)
- 纹理填充方式
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
- 纹理采样方式
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
Mipmap
纹理精度高于物体显示精度时,用Mipmap解决取样问题
生成一组金字塔型的图片 :6464、3232、1616…11
生成不同Level的纹理
- Level = 0: 128*128
- Level = 1: 64*64
- Level = 2: 32*32
- Level = 3: 16*16
远处采用level大的纹理
利用屏幕像素的相邻像素点估算
如果Mipmap level D = logL不是整数
- 四舍五入后,在对应图层上双线性插值
- 三线性插值:
- 对D向上、向下取整
- 分别双线性插值后,再对[D, D+1]线性插值
先设置Mipmap Level:glTexImage2D(GL_TEXTURE_*D, level, …)
level默认为0
GLU mipmap builder
- gluBuild2DMipmaps(…)
Mipmap采样方式
- 当前图层的采样方式 + 取用哪个图层方式
- GL_NEAREST_MIPMAP_NEAREST
- GL_LINEAR_MIPMAP_NEAREST
- GL_NEAREST_MIPMAP_LINEAR
- GL_LINEAR_MIPMAP_LINEAR
Mapping a Texture
通过glTexCoord*()设置每个顶点的纹理坐标
对绘制物体设置纹理坐标
例如
• glBegin(GL_TRIANGLES);
glColor3f(r0, g0, b0);
glNormal3f(u0, v0, w0);
glTexCoord2f(s0, t0);
glVertex3f(x0, y0, z0);
glColor3f(r1, g1, b1);
glNormal3f(u1, v1, w1);
glTexCoord2f(s1, t1);
glVertex3f(x1, y1, z1);
……
• glEnd();
纹理坐标
-
OpenGL可以自动生成纹理坐标
- glTexGen{ifd}[v](GL_S, GL_TEXTURE_GEN_MODE, params)
- 生成模式params
- GL_OBJECT_LINEAR(固定纹理)
- GL_EYE_LINEAR(按视角变动纹理)
- GL_SPHERE_MAP(环境映射)
-
设置投影平面
- glTexGenfv(GL_T, GL_OBJECT_PLANE, xPlane)
-
启用
- glEnable(GL_TEXTURE_GEN_S)
- glEnable(GL_TEXTURE_GEN_T)
-
关闭glDisable
圆柱体
圆柱体可以展开为平面,圆柱体的参数坐标是(φ,y)(\varphi,y)(φ,y)
- x=rcosφx=rcos\varphix=rcosφ
- y=yy=yy=y
- z=rsinφz=rsin\varphiz=rsinφ
- φ∈[0,2π],y∈[−h,h]\varphi\isin[0,2\pi], y\isin[-h,h]φ∈[0,2π],y∈[−h,h]
圆柱上点(φ,y)(\varphi,y)(φ,y)映射到纹理空间
- s=φ/2πs=\varphi/2\pis=φ/2π
- t=(y+h)/2ht=(y+h)/2ht=(y+h)/2h
根据参数方程,生成 - 顶点坐标:(rcosφ,y,rsinφ)(rcos\varphi,y,rsin\varphi)(rcosφ,y,rsinφ)
- 法向量:(cosφ,0,sinφ)(cos\varphi,0,sin\varphi)(cosφ,0,sinφ)
- 纹理坐标:(φ/2π,y/h)(\varphi/2\pi,y/h)(φ/2π,y/h)
球面
球面的参数坐标是(θ,φ)(\theta, \varphi)(θ,φ)
- x=rsinθcosφx=rsin\theta cos\varphix=rsinθcosφ
- y=rsinθsinφy=rsin\theta sin\varphiy=rsinθsinφ
- z=rcosθz=rcos\thetaz=rcosθ
- θ∈[0,π],φ∈[0,2π]\theta\isin[0,\pi],\varphi\isin[0,2\pi]θ∈[0,π],φ∈[0,2π]
球面上点(θ,φ)(\theta,\varphi)(θ,φ)映射到纹理空间
- s=φ/2πs=\varphi/2\pis=φ/2π
- t=θ/πt=\theta/\pit=θ/π
根据参数方程,生成
- 顶点坐标:(rsinθcosφ,rsinθsinφ,rcosθ)(rsin\theta cos\varphi,rsin\theta sin\varphi, rcos\theta)(rsinθcosφ,rsinθsinφ,rcosθ)
- 法向量:(sinθcosφ,sinθsinφ.cosθ)(sin\theta cos\varphi,sin\theta sin\varphi.cos\theta)(sinθcosφ,sinθsinφ.cosθ)
- 纹理坐标:(φ/2π,θ/π)( \varphi/2\pi,\theta/\pi)(φ/2π,θ/π)
正方体
- 正面z = 1
- 反面z = -1
- 右面x = 1
- 左面x = -1
- 上面y = 1
- 下面y = -1
一般物体
Intermediate Mapping Methods
基于投射,把物体投射到中间曲面:平面/圆柱体/球面/正方体
平面投射
圆柱体投射
从物体中心到顶点的射线与圆柱体交点(相交于侧面、圆盘)
球体投射
南北极变形严重
立方体投射
不变形、速度快
标准立方体:
- 右面0(x>0),左面1(x<0)
- 上面2(y>0),下面3(y<0)
- 正面4(z>0),反面5(z<0)