计算机图形学

Similar documents
计算机图形学

Microsoft PowerPoint - cg_ch09_02

슬라이드 1

OpenGL Render

Outline 三角網格資料結構 一般繪圖方式 硬體加速繪圖方式 Display List Vertex Array 序列式 :gldrawarrays 索引式 :gldrawelements Vertex Buffer Object 序列式 索引式

chap02_part2

.., + +, +, +, +, +, +,! # # % ( % ( / 0!% ( %! %! % # (!) %!%! # (!!# % ) # (!! # )! % +,! ) ) &.. 1. # % 1 ) 2 % 2 1 #% %! ( & # +! %, %. #( # ( 1 (

# % & ) ) & + %,!# & + #. / / & ) 0 / 1! 2

高级计算机图形学

PowerPoint Presentation

chap07.key

PowerPoint 演示文稿

Microsoft PowerPoint - cg_ch02_01

%! # # % % & # ( ) ( +, & +, +, & +, & +, +, &!

01

# ( + + # + # 6 +,! + # +! +, + # ( + ) ( + ( + ) + 7! + # + /8 + ) ( +! + #. + ( +, +! + # + # + + ( ! ( + ) ( + ) +, + ( + 9% +! +, + ( +

<4D F736F F D20CEC4BCFEB6FEA3BA31385FA1B C4EABAFEC4CFCAA1BDF0C8DAD4CBD0D0B1A8B8E6A1B7B6A8B8E5A3A8574F5244CEC4BCFEA3A9>

幻灯片 1

2015年全国射箭冠军赛.xls

高级计算机图形学



ii

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

入 指 令 如 : 鍵 盤 鼠 標 多 點 觸 控 重 力 感 應 陀 螺 儀 等 4. 圖 形 用 戶 接 口 掌 握 引 擎 API 中 GUI 與 GUILayout 類 中 方 法 和 變 量 的 使 用, 能 夠 通 過 GUI Skin 為 應 用 的 界 面 定 制 不 同 風 格 主


# 7 % % % < % +!,! %!!

14052_公開用.pdf

<4D F736F F D20B8B4BCFE20D7DCB5C4CEC4BCFE2E646F6378>

2 g g g g g g g

untitled

! + +, ) % %.!&!, /! 0! 0 # ( ( # (,, # ( % 1 2 ) (, ( 4! 0 & 2 /, # # ( &

壹、學校背景

游戏攻略大全(十).doc

Microsoft Word - 人民萬歲_宋玉雯.docx

二零一五年施政報告 - 施政綱領 - 第三章 扶貧及為弱勢社群提供支援

育 部 分 則 由 陳 淑 貞 委 員 及 李 兆 環 委 員 共 同 執 行, 在 此 先 感 謝 各 位 委 員 及 學 者 專 家 之 參 與 二 目 前 評 論 報 告 初 稿 之 架 構 區 分 為 對 政 府 機 關 回 應 意 見 之 觀 察 優 點 及 待 改 進 事 項, 以 及

<4D F736F F D20BACBB0B2C8ABD3EBB7C5C9E4D0D4CEDBC8BEB7C0D6CEA1B0CAAEB6FECEE5A1B1B9E6BBAEBCB C4EAD4B6BEB0C4BFB1EA2E646F63>

<4F4BBEFAA576A470BBA15FC160AAED E786C73>

58, ,769 51,911 74,666 35, , , , ,

辽宁铁~1

保 险 公 司 金 富 月 盈 两 产 全 品 保 名 险 称 ( 分 红 型 ) 产 分 品 红 类 型 缴 费 年 类 缴 型 缴 10 费 年 期 缴 限 保 险 期 限 ( 年 ) 聚 富 2 号 两 全 保 险 ( 万 能 型 ) 万 能 型 趸 缴 趸 缴 6 年 龙 享 安 康 重 疾

I

海底捞你学不会

YEN/MIAO CHING MS 27FEB DEL HKG

Microsoft Word - 02文本.docx

最新监察执法全书(十一).doc

钓鱼技巧_二_.doc

动物的智慧(五)

健康知识(一)

北京(一)

i

园林植物卷(九).doc

家装知识(四)

认识植物(一)

药用植物种植技术(二)

司法鉴定工作手册(十八)

外科疾病诊治(三)

动物杂谈_三_.doc

untitled

外科疾病诊治(十九)

养虾小常识_二_.doc

养虾小常识_三_.doc

Transcription:

高级计算机图形学 中国科学技术大学计算机学院 黄章进 zhuang@ustc.edu.cn

第十章之第四节 GLSL(III) 2

内容 OpenGL 与着色器的通信 attribute 变量 uniform 变量 着色器示例 顶点着色器 片段着色器 3

连接着色器与 OpenGL 调用 glcreateshader 创建着色器对象 调用 glshadersource 为着色器加载源代码 调用 glcompileshader 编译每个着色器 调用 glcreateprogram 创建程序对象 调用 glattachshader 把着色器对象连接到程序对象 调用 gllinkprogram 链接程序对象, 生成可执行程序 调用 gluseprogram 安装可执行程序替换 OpengGL 固定功能流水线处理模块 用 uniform 和 attribute 变量在应用程序和着色器间通信 4

应用程序 -> 着色器通信 OpenGL 应用程序有两种方式向着色器发送值 使用内置和用户定义的全局变量 uniform 变量 attribute 变量 使用纹理 纹理可解释为图像或数据数组 5

内置顶点属性 内置顶点属性 gl_color /gl_normal /gl_vertex 等 glbegin/glend 间用 glcolor /glnormal /glvertex 等函数指定 顶点数组方式 6

活动属性变量 活动 (active) 属性变量 : 由编译器和链接器决定的顶点着色器执行时会访问的属性 仅只声明从不使用的是非活动属性 程序对象链接失败, 如果活动的内置和自定义属性数目多于 GL_MAX_VERTEX_ATTRIBS (16) 7

自定义顶点属性 当程序对象成功链接后, 链接器生成一张活动属性变量名表 用 glgetattriblocation 查询活动属性变量的内存位置 在 glbegin/glend 间调用 glvertexattrib 给属性变量置值, 或通过 glvertexattribpointer 和 glenablevertexattribarray 来使用顶点数组 8

获取属性变量的索引 GLint glgetattriblocation(gluint program, const GLchar *name); 返回上一次链接时绑定到程序对象 program 中活动属性变量 name 的索引 如果 name 不是 program 的一个活动属性变量, 或是内置属性变量 ( 以 gl_ 开头 ), 返回 -1 如果 name 是活动属性矩阵, 返回矩阵第一列的索引 后一列的索引为前一列的索引加 1 9

显式绑定索引 void glbindattriblocation(gluint program, GLuint index, const GLchar *name); 指定下一次链接时绑定到程序对象 program 中属性变量 name 的索引为 index 如果 name 是内置属性变量 ( 以 gl_ 开头 ), 产生一个 GL_ INVALID_OPERATION 错误 如果 name 之前绑定过, 则索引被 index 替换 如果 name 是属性矩阵,index 绑定到第一列 index 取值 [0, GL_MAX_VERTEX_ATTRIBS-1] 程序成功链接后, 绑定才生效 10

设置顶点属性的值 void glvertexattrib{1234}{sfd}(gluint index, TYPE values); void glvertexattrib{1234}{sfd}v(gluint index, const TYPE *values); void glvertexattrib4{bsifd ubusui}v(gluint index, const TYPE *values); 设置索引为 index 的属性变量 (vec4) 的值 如果没有显式设置所有 4 个值,y 和 z 默认为 0.0,w 为 1.0 设置 n(=2,3,4) 列矩阵的属性值, 需要调用 n 次 glvertexattrib*() 分别为每一列加载值 属性 0 对应于内置属性 gl_vertex, 从而调用 glvertex 和以索引为 0 调用 glvertexattrib 等价 11

例子 顶点着色器中 : attribute float height; OpenGL 中 : GLint loc = glgetattriblocation(p,"height"); glbegin(gl_triangle_strip); glvertexattrib1f(loc,2.0); glvertex2f(-1,1); glvertexattrib1f(loc,2.0); glvertex2f(1,1); glvertexattrib1f(loc,-2.0); glvertex2f(-1,-1); glvertexattrib1f(loc,-2.0); glvertex2f(1,-1); glend(); 12

顶点属性数组 void glvertexattribpointer(gluint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); 为索引值为 index 的属性变量的数组指定位置 pointer 和数据格式 void glenablevertexattribarray(gluint index) void gldisablevertexattribarray(gluint index) 启用 / 禁用属性 index 的顶点属性数组 启用后, 就可用 gldrawarrays() 等来为顶点属性变量加载值 13

例子 顶点着色器中 : attribute float height; OpenGL 中 : float vertices[8] = {-1,1, 1,1, -1,-1, 1,-1}; float heights[4] = {2,2,-2,-2}; GLint loc = glgetattriblocation(p,"height"); glenableclientstate(gl_vertex_array); glenablevertexattribarray(loc); glvertexpointer(2,gl_float,0,vertices); glvertexattribpointer(loc,1,gl_float,0,0,heights); 14

一致 (uniform) 变量 一致变量的值在图元 / 帧 / 场景内保持不变 内置 : 变换矩阵 裁剪平面 光源 材料 雾 用户定义 活动一致变量 : 由编译器和链接器决定的着色器执行时会访问的一致变量 程序对象链接失败, 如果活动的内置和自定义一致变量数目多于 GL_MAX_VERTEX_UNIFORM_COMPONENTS (512) 15

指定一致变量 当程序对象成功链接后, 链接器生成一张活动一致变量名表, 变量初值置为 0(GL_FALSE) 用 glgetuniformlocation 查询活动一致变量的内存位置 调用 gluniform 给一致变量加载值 不同于属性变量, 一致变量的位置 ( 索引 ) 不能显式指定 16

获取一致变量的索引 GLint glgetuniformlocation(gluint program, const GLchar *name); 返回上一次链接时绑定到程序对象 program 中活动一致变量 name 的索引 如果 name 不是 program 的一个活动一致变量, 或是保留一致变量 ( 以 gl_ 开头 ), 返回 -1 name 不能是结构 结构数组 向量 / 矩阵的部分 对结构和数组, 在 name 里用. 和 [] 来指定结构字段和数组元素 数组第一个元素的位置可在 name 中用数组名或数组名加 [0] 获取 17

设置一致变量的值 void gluniform{1234}{if}( GLint location, TYPE values ); void gluniform{1234}{if}v( GLint location, GLsizei count, const TYPE *values ); void gluniformmatrix{234}fv( GLint location, GLsizei count, GLboolean transpose, const GLfloat *values ); void gluniformmatrix{2x3,3x2,2x4,4x2,3x4,4x3}fv( GLint location, GLsizei count, GLboolean transpose, const GLfloat *values ); 设置当前使用程序对象在位置 location 的一致变量的值 18

设置一致变量的值 向量形式把 count 组值加载到 uniform 数组的 location 位置开始的 count 个元素 这里,location 不是数组元素下标 矩阵形式中的 transpose 为 GL_TURE 表示 values 按行主序指定 ; 否则, 按列主序指定 上述函数可用于加载布尔型变量, 自动转换类型 当函数名指定的大小和类型 ( 除去布尔型 ) 和着色器中声明的 uniform 变量不匹配时, 报错 当 count>1, 而着色器中声明的 uniform 变量不是数组时, 报错 19

例子 着色器中 : uniform float specintensity; uniform vec4 speccolor; uniform float t[2]; uniform vec4 colors[3]; 20

例子 ( 续 ) OpenGL 中 : GLint loc1,loc2,loc3,loc4; float specintensity = 0.98; float sc[4] = {0.8,0.8,0.8,1.0}; float threshold[2] = {0.5,0.25}; float colors[12] = {0.4,0.4,0.8,1.0, 0.2,0.2,0.4,1.0, 0.1,0.1,0.1,1.0}; loc1 = glgetuniformlocation(p,"specintensity"); gluniform1f(loc1, specintensity); loc2 = glgetuniformlocation(p,"speccolor"); gluniform4fv(loc2, 1, sc); loc3 = glgetuniformlocation(p,"t"); gluniform1fv(loc3, 2, threshold); loc4 = glgetuniformlocation(p,"colors"); gluniform4fv(loc4, 3, colors); 21

uniform 向量和数组 着色器中 : uniform vec4 speccolor; uniform float t[2]; OpenGL 中 : GLint loc1,loc2,loc3; float sc[4] = {0.8,0.8,0.8,1.0}; float threshold[2] = {0.5,0.25}; loc2 = glgetuniformlocation(p,"speccolor"); gluniform4f(loc2, sc[0], sc[1], sc[2], sc[3]); // gluniform4fv(loc2, 1, sc); /* 等价形式 */ loct0 = glgetuniformlocation(p, "t[0]"); gluniform1f(loct0, threshold[0]); loct1 = glgetuniformlocation(p, "t[1]"); gluniform1f(loct1, threshold[1]); 22

着色器示例 顶点着色器 波动 渐变 粒子系统 非真实感着色 Phong 光照 片段着色器 Phong 光照 环境映射 凹凸映射 23

波动顶点着色器 uniform float time; uniform float xs, zs, // frequencies uniform float h; // height scale void main() { vec4 t = gl_vertex; t.y = gl_vertex.y + h*sin(time + xs*gl_vertex.x) + h*sin(time + zs*gl_vertex.z); gl_position = gl_modelviewprojectionmatrix*t; } attribute 变量和 uniform 变量在顶点着色器内只读 24

Glint timeparam; timeparam = glgetuniformlocation(program, "time"); void idle() { gluniform1f(timeparam, (GLfloat) glutget(glut_elapsed_time)); glutpostredisplay(); } 25

渐变 (morphing) 效果 渐变 : 一个物体平滑地变换到另一个物体 假设两个物体的顶点有一一对应关系 顶点着色器需要输出一个由对应顶点对插值得到的顶点 26

一个顶点通过 gl_vertex 传入, 对应顶点用顶点属性变量传入 attribute vec4 vertices2; uniform float time; void main() { float s = 0.5*(1.0+sin(0.001*time)); vec4 t = mix(gl_vertex, vertices2, s); gl_position = gl_modelviewprojectionmatrix*t; gl_frontcolor = gl_color; } mix(x, y, a) 返回 x * (1.0-a) + y * a 27

GLint vertices2param; vertices2param = glgetattriblocation(program, "vertices2"); #define N 50 GLfloat vertices_one[n][3], vertices_two[n][3]; glbegin(gl_triangles); for (int i = 0; i < N; i++) { glvertexattrib3fv(vertices2param, vertices_two[i]); glvertex3fv(vertices_one[i]); } glend(); 28

粒子 (particle) 系统 粒子系统的基本思想 : 用真实或自定义物理规律来控制粒子的运动 每一时间步, 要为每个粒子确定一个新位置 考虑符合牛顿定律的质点, 质量为 m, 初始位置为 (x 0,y 0,z 0 ), 初始速度为 (v x,v y,v z ), 重力加速度为 g, 则在 t 时刻的位置为 x(t) = x 0 + v x t, y(t) = y 0 + v y t + g t 2 / (2m), z(t) = z 0 + v z t. 29

attribute vec3 vel; // 初始速度 uniform float g, m, t; void main() { vec3 object_pos; object_pos.x = gl_vertex.x + vel.x * t; object_pos.y = gl_vertex.y + vel.y * t + g/(2.0*m)*t*t; object_pos.z = gl_vertex.z + vel.z * t; gl_position = gl_modelviewprojectionmatrix * vec4(object_pos,1); } 30

非真实感着色 根据光线和法向的夹角给对象赋两种颜色 根据视线和方向的夹角把对象轮廓赋为黑色 const vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0); const vec4 red = vec4(1.0, 0.0, 0.0, 1.0); const vec4 black = vec4(0.0, 0.0, 0.0, 1.0); if(dot(l, N) > 0.5) gl_frontcolor = yellow; else gl_frontcolor = red; if(abs(dot(e, N)) < 0.1) glfrontcolor = black; 31

Phong 光照模型 I =k d I d I =k d I d l n + k s I s (r v ) α + k a I a l n + k s I s (n h ) β + k a I a 32

内置 uniform 变量 struct gl_lightsourceparameters { vec4 ambient; // Acli vec4 diffuse; // Dcli vec4 specular; // Scli vec4 position; // Ppli vec4 halfvector; // Derived: Hi vec3 spotdirection; // Sdli float spotexponent; // Srli float spotcutoff; // Crli // (range: [0.0,90.0], 180.0) float spotcoscutoff; // Derived: cos(crli) // (range: [1.0,0.0],-1.0) float constantattenuation; // K0 float linearattenuation; // K1 float quadraticattenuation; // K2 }; uniform gl_lightsourceparameters gl_lightsource[gl_maxlights]; 33

struct gl_lightmodelparameters { vec4 ambient; // Acs }; uniform gl_lightmodelparameters gl_lightmodel; struct gl_materialparameters { vec4 emission; // Ecm vec4 ambient; // Acm vec4 diffuse; // Dcm vec4 specular; // Scm float shininess; // Srm }; uniform gl_materialparameters gl_frontmaterial; uniform gl_materialparameters gl_backmaterial; 34

Phong 光照 光源位置 gl_lightsource[i].position 在视点坐标系中给出 视点在视点坐标系的原点 N: 视点坐标系中的法向量 L: 视点坐标系中的顶点到光源向量 ( 光线 ) E: 视点坐标系中的顶点到视点向量 ( 视线 ) R: 视点坐标系中的理想反射向量 H: 视点坐标系中 L 和 E 的中值向量 35

改进的 Phong 顶点着色器 I void main(void) /* modified Phong vertex shader (without distance term) */ { gl_position = gl_modelviewprojectionmatrix * gl_vertex; vec4 ambient, diffuse, specular; vec4 eyeposition = gl_modelviewmatrix * gl_vertex; vec4 eyelightpos = gl_lightsource[0].position; vec3 N = normalize(gl_normalmatrix * gl_normal); vec3 L = normalize(eyelightpos.xyz - eyeposition.xyz); vec3 E = -normalize(eyeposition.xyz); vec3 H = normalize(l + E); 36

改进的 Phong 顶点着色器 II /* compute diffuse, ambient, and specular contributions */ float f = 1.0; float Kd = max(dot(l, N), 0.0); float Ks = pow(max(dot(n, H), 0.0), gl_frontmaterial.shininess); if (dot(l,n) < 0.0) f = 0.0; ambient = gl_frontlightproduct[0].ambient; diffuse = Kd*gl_FrontLightProduct[0].diffuse; specular = f*ks*gl_frontlightproduct[0].specular; } gl_frontcolor = ambient+diffuse+specular; 37

基于片段的 Phong 光照 利用 varying 变量把属性从顶点着色器传递到片断着色器 法向量 N 光线向量 L 视线向量 E 38

基于片段光照的顶点着色器 varying vec3 N, L, E; void main() { gl_position = gl_modelviewprojectionmatrix * gl_vertex; vec4 eyeposition = gl_modelviewmatrix * gl_vertex; vec4 eyelightpos = gl_lightsource[0].position; } N = normalize(gl_normalmatrix * gl_normal); L = normalize(eyelightpos.xyz - eyeposition.xyz); E = -normalize(eyeposition.xyz); 39

改进 Phong 光照片段着色器 I varying vec3 N; varying vec3 L; varying vec3 E; void main() { vec3 Normal = normalize(n); vec3 Light = normalize(l); vec3 Eye = normalize(e); vec3 Half = normalize(eye + Light); 40

改进 Phong 光照片段着色器 II float f = 1.0; float Kd = max(dot(normal, Light), 0.0); float Ks = pow(max(dot(half, Normal), 0.0), gl_frontmaterial.shininess); vec4 diffuse = Kd * gl_frontlightproduct[0].diffuse; if (dot(normal, Light) < 0.0) f = 0.0; vec4 specular = f * Ks * gl_frontlightproduct[0].specular; vec4 ambient = gl_frontlightproduct[0].ambient; } gl_fragcolor = ambient + diffuse + specular; 41

效果对比 逐顶点光照 逐片段光照 42

采样器 (Samplers) 提供对纹理对象的访问 定义了 1, 2, 和 3 维纹理以及立方体贴图的采样器 在着色器中 : uniform sampler2d mytexture; vec2 texcoord; vec4 texcolor = texture2d(mytexture, texcoord); 在应用程序中 : texmaplocation = glgetuniformlocation(myprog, mytexture ); gluniform1i(texmaplocation, 0); /* assigns to texture unit 0 */ 43

片段着色器的应用 纹理映射 平滑明暗环境映射凹凸映射 44

立方体贴图 用六张 2D 纹理图组成立方图纹理 OpenGL 支持立方体贴图 GLSL 通过立方图采采样器来支持 vec4 texcolor = texturecube(mycube, texcoord); 纹理坐标必须是 3D 的 45

立方图纹理示例 46

环境映射 用反射向量在立方图中定位纹理 47

用着色器实现环境映射 通常在世界坐标系中计算环境映射, 由于模型矩阵的作用, 世界坐标系可能会不同于对象坐标系 对象的位置和法向在对象坐标系中指定 把模型矩阵作为 uniform 变量传递给着色器 也可用于反射贴图或折射贴图 ( 例如模拟水 ) 48

反射贴图顶点着色器 varying vec3 R; void main(void) { gl_position = gl_modelviewprojectionmatrix*gl_vertex; vec3 N = normalize(gl_normalmatrix*gl_normal); vec4 eyepos = gl_modelviewmatrix*gl_vertex; R = reflect(-eyepos.xyz, N); } 49

反射贴图片段着色器 varying vec3 R; uniform samplercube texmap; void main(void) { gl_fragcolor = texturecube(texmap, R); } 50

凹凸映射 对每个片段扰动法向 把扰动存储为纹理 51

第 4 次作业 :GLSL 着色器 网格显示 : 可对网格进行交互式观察 顶点变换动画 : 用顶点着色器实现例如波动效果的网格 基于片段的 Phong 明暗处理 : 有距离衰减项, 可考虑实现不同类型光源 ( 方向光 点光源 聚光灯 ) 技术 + 创意 2010-1-5 前提交 52