最近因为工作需要阅读《Cocos2D-X 3.X 3D图形学渲染技术讲解》这本书所做的笔记。

GPU 语言

  1. OpenGL : GLSL
  2. DirectX : HLSL
  3. Nvidia :CG

GLSL

构成

  1. Vertex Shader : 顶点着色器
  2. Fragment Shader : 片段着色器
  3. Geometry Shader :几何着色器(比较少见)

简述

  1. 顶点着色器中一般都有 out 变量,对应的片段着色器中用 in ,两个变量的命名相同,类型也必须相同。
  2. 片段着色器变量必须是 vec4
  3. uniform 是全局的,也就是独一无二的,同时它可以被着色器程序的任意着色器在任意阶段访问。顶点着色器中不需要这个uniform,所以不需要在顶点着色器中定义。可以在C++中通过代码调用OpenGL的接口进行设置。
  4. GPU是多线程的,所以在shader编程中最好不用if else 、for、while等条件判断或循环语句,这样不利于GPU的多线程运行。

OpenGL编程

着色器

uniform

该字段申明的变量是外部程序传给顶点(Vertex)着色器、片段(Fragment)着色器的变量。

该字段是一种从CPU应用向GPU中的着色器发送数据的方式。它是全局的,故而在每个着色器程序中必须保证其对象是唯一的。

可以在任意着色器中的任意阶段中访问,它会一致保持它的数据直到被

该变量是常量,类似C++中的const,不能被shader程序修改,只能使用。

如果声明之后没有用过,那么编辑器会默认移除这个变量。(如果只是在着色器内用,不需要任何声明修饰,直接定义使用就可以了)

通过glGetUniformLocation 函数查询uniform变量,用glUniformxx() 函数赋值。

    GLint vertexColorLocation = glGetUniformLocation(shaderProgram, "vertexColor");glUseProgram(shaderProgram);glUniform4f(vertexColor,0.0f,1.0f,0.0f,1.0f);

作用: 一般用于变换矩阵材质光照参数颜色等。

attribute

该变量只能在顶点(Vertex)着色器中申明和使用。

作用:一般用来表示一些顶点数据,例如:顶点坐标法线纹理坐标顶点颜色等等

使用函数glBindAttribLocation来绑定每一个该变量的位置,接着使用函数glVertexAttribPointer为其赋值。

varying

该变量主要用于Vertex和Fragment之间传递数据的。

一般流程是在Vertex中修改改变量,在Fragment中使用该变量。必须声明一致。

main

每个着色器的入口都是main函数,在这个函数中处理所有的输入变量,并将结果输出到输出变量中。

in && out

定义输入和输出的。 每个着色器是独立的,但也是整体的一部分。也就是,每个都有自己的输出和输入。inout的作用就是用来输入和输出。

只要一个着色器的输出变量和下一个着色器的输入变量匹配,这个数据就会一致传递下去。

顶点着色器需要从顶点数据中直接输入。

片段着色器需要一个vec4 的变量作为输出。目的是因为片段着色器需要输出最终的颜色,如果不指定颜色,那么就会默认输出黑色或者白色。

因此可以看出,如果需要从一个着色器向另一个着色器发送数据,则必须在发送方着色器和接收方着色器中声明一样类型一样名字的变量。

VBO (Vertex Buffer Object) 顶点缓冲对象

可以看出来,三个顶点的在内存中的排列顺序,是XYZ+RGB进行排列的。

        //位置属性glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,6 * sizeof(GLfloat),(GLvoid*) 0);glEnableVertexAttribArray(0);//颜色属性glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,6 * sizeof(GLfloat),(GLvoid*) (3 * sizeof(GLfloat)));glEnableVertexAttribArray(1);

函数glVertexAttribPointer 的作用是指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置。

index:第几个属性,从0开始取,0,1,2,顺序自己定义,例如顶点位置,纹理,法线。

size:一个顶点所有数据的个数,坐标(XYZ)和颜色(RGB)都占3个float,所以是3

type:顶点描述数据的类型,这里position数组中的数据全部为float,所以是GL_FLOAT

normalized:是否需要显卡帮忙把数据归一化到-1到+1区间,这里不需要,所以设置GL_FALSE

stride:一个顶点占有的总的字节数。这里是6个float (xyzrgb),所以是6 * sizeof(GLfloat)

pointer:当前指针指向的vertex内部的偏离字节数,可以唯一的标识顶点某个属性的偏移量。第一个是0,顶点位置的属性。第二个是颜色,紧接着位置之后的,所以是 3 * sizeof(GLfloat)



矩阵变换算法

矩阵平移变换算法

原理: 在原始向量的基础上加上另一个向量,从而获得一个在不同位置的新向量。

三维坐标无法完成平移变换,需要将三维的点转换成四维的点。四维的点称为齐次坐标,本质就是在三维坐标的基础上加上一位w。

假设点为P(x,y,z),平移向量

T ⃗ ( T x , T y , T z ) \vec{T}(T_x,T_y,T_z) T (Tx​,Ty​,Tz​)

可以用如下公式:

∣ 1 0 0 T x 0 1 0 T y 0 0 1 T z 0 0 0 1 ∣ ⋅ { x y z 1 } = { x + T x y + T y z + T z 1 } \left| \begin{matrix} 1 & 0 & 0 & T_x \\ 0 & 1 & 0 & T_y \\ 0 & 0 & 1 & T_z \\ 0 & 0 & 0 & 1 \end{matrix} \right| \cdot \left\{ \begin{matrix} x \\ y \\ z \\ 1 \end{matrix} \right\} = \left\{ \begin{matrix} x + T_x \\ y + T_y \\ z + T_z \\ 1 \end{matrix} \right\} ∣ ∣​1000​0100​0010​Tx​Ty​Tz​1​∣ ∣​⋅⎩ ⎨ ⎧​xyz1​⎭ ⎬ ⎫​=⎩ ⎨ ⎧​x+Tx​y+Ty​z+Tz​1​⎭ ⎬ ⎫​

cocos2dx中相关代码

//创建矩阵的平移函数
void Mat4::createTranslation(const Vec3& translation, Mat4* dst)
{GP_ASSERT(dst);memcpy(dst, &IDENTITY, MATRIX_SIZE);dst->m[12] = translation.x;dst->m[13] = translation.y;dst->m[14] = translation.z;
}
void Mat4::createTranslation(float xTranslation, float yTranslation, float zTranslation, Mat4* dst)
{GP_ASSERT(dst);memcpy(dst, &IDENTITY, MATRIX_SIZE);dst->m[12] = xTranslation;dst->m[13] = yTranslation;dst->m[14] = zTranslation;
}

矩阵旋转变换算法

原理:定义一个角,和旋转轴,物体沿着给定的轴旋转特定的角度,从而实现旋转功能。

  • X轴:在屏幕上的方向从左指向右。

  • Y轴:在屏幕上的方向是从下指向上。

  • Z轴:在屏幕上分为两种:

    1. 屏幕里指向外,通常称为右手坐标系。
    2. 屏幕外指向内,通常称为左手坐标系。

旋转

主要分为3种。

  1. 绕X轴旋转
  2. 绕Y轴旋转
  3. 绕Z轴旋转

还有其他旋转组合,比如 XZ轴XYZ轴等等

绕X轴

公式如下:

∣ 1 0 0 0 0 cos ⁡ θ − sin ⁡ θ 0 0 sin ⁡ θ cos ⁡ θ 0 0 0 0 1 ∣ ⋅ { x y z 1 } = { x y ⋅ cos ⁡ θ − z ⋅ sin ⁡ θ y ⋅ sin ⁡ θ + z ⋅ cos ⁡ θ 1 } \left| \begin{matrix} 1 & 0 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta &0 \\ 0 & \sin\theta & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right| \cdot \left\{ \begin{matrix} x \\ y \\ z \\ 1 \end{matrix} \right\} = \left \{ \begin{matrix} x \\ y \cdot \cos\theta - z \cdot \sin\theta \\ y \cdot \sin\theta + z \cdot \cos\theta \\ 1 \end{matrix} \right\} ∣ ∣​1000​0cosθsinθ0​0−sinθcosθ0​0001​∣ ∣​⋅⎩ ⎨ ⎧​xyz1​⎭ ⎬ ⎫​=⎩ ⎨ ⎧​xy⋅cosθ−z⋅sinθy⋅sinθ+z⋅cosθ1​⎭ ⎬ ⎫​

cocos2dx中代码:

void Mat4::createRotationX(float angle, Mat4* dst)
{GP_ASSERT(dst);memcpy(dst, &IDENTITY, MATRIX_SIZE);float c = std::cos(angle);float s = std::sin(angle);dst->m[5]  = c;dst->m[6]  = s;dst->m[9]  = -s;dst->m[10] = c;
}

绕Y轴

公式如下:

∣ cos ⁡ θ 0 sin ⁡ θ 0 0 1 0 0 − sin ⁡ θ 0 cos ⁡ θ 0 0 0 0 1 ∣ ⋅ { x y z 1 } = { x ⋅ cos ⁡ θ + z ⋅ sin ⁡ θ y − x ⋅ sin ⁡ θ + z ⋅ cos ⁡ θ 1 } \left| \begin{matrix} \cos\theta & 0 & \sin\theta & 0 \\ 0 & 1 & 0 &0 \\ -\sin\theta & 0 & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right| \cdot \left\{ \begin{matrix} x \\ y \\ z \\ 1 \end{matrix} \right\} = \left \{ \begin{matrix} x \cdot \cos\theta + z \cdot \sin\theta \\ y \\ -x \cdot \sin\theta + z \cdot \cos\theta \\ 1 \end{matrix} \right\} ∣ ∣​cosθ0−sinθ0​0100​sinθ0cosθ0​0001​∣ ∣​⋅⎩ ⎨ ⎧​xyz1​⎭ ⎬ ⎫​=⎩ ⎨ ⎧​x⋅cosθ+z⋅sinθy−x⋅sinθ+z⋅cosθ1​⎭ ⎬ ⎫​

cocos2dx中的代码如下:

void Mat4::createRotationY(float angle, Mat4* dst)
{GP_ASSERT(dst);memcpy(dst, &IDENTITY, MATRIX_SIZE);float c = std::cos(angle);float s = std::sin(angle);dst->m[0]  = c;dst->m[2]  = -s;dst->m[8]  = s;dst->m[10] = c;
}

绕Z轴

公式如下:

∣ cos ⁡ θ − sin ⁡ θ 0 0 sin ⁡ θ cos ⁡ θ 0 0 0 0 1 0 0 0 0 1 ∣ ⋅ { x y z 1 } = { x ⋅ cos ⁡ θ − y ⋅ sin ⁡ θ x ⋅ sin ⁡ θ + y ⋅ cos ⁡ θ z 1 } \left| \begin{matrix} \cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta & \cos\theta & 0 & 0 \\ 0 & 0 & 1 &0 \\ 0 & 0 & 0 & 1 \end{matrix} \right| \cdot \left\{ \begin{matrix} x \\ y \\ z \\ 1 \end{matrix} \right\} = \left \{ \begin{matrix} x \cdot \cos\theta - y \cdot \sin\theta \\ x \cdot \sin\theta + y \cdot \cos\theta \\ z \\ 1 \end{matrix} \right\} ∣ ∣​cosθsinθ00​−sinθcosθ00​0010​0001​∣ ∣​⋅⎩ ⎨ ⎧​xyz1​⎭ ⎬ ⎫​=⎩ ⎨ ⎧​x⋅cosθ−y⋅sinθx⋅sinθ+y⋅cosθz1​⎭ ⎬ ⎫​

cocos2dx中的代码如下:

void Mat4::createRotationZ(float angle, Mat4* dst)
{GP_ASSERT(dst);memcpy(dst, &IDENTITY, MATRIX_SIZE);float c = std::cos(angle);float s = std::sin(angle);dst->m[0] = c;dst->m[1] = s;dst->m[4] = -s;dst->m[5] = c;
}

绕某个向量旋转

cocos2dx中的实现方法

void Mat4::createRotation(const Quaternion& q, Mat4* dst)
{GP_ASSERT(dst);float x2 = q.x + q.x;float y2 = q.y + q.y;float z2 = q.z + q.z;float xx2 = q.x * x2;float yy2 = q.y * y2;float zz2 = q.z * z2;float xy2 = q.x * y2;float xz2 = q.x * z2;float yz2 = q.y * z2;float wx2 = q.w * x2;float wy2 = q.w * y2;float wz2 = q.w * z2;dst->m[0] = 1.0f - yy2 - zz2;dst->m[1] = xy2 + wz2;dst->m[2] = xz2 - wy2;dst->m[3] = 0.0f;dst->m[4] = xy2 - wz2;dst->m[5] = 1.0f - xx2 - zz2;dst->m[6] = yz2 + wx2;dst->m[7] = 0.0f;dst->m[8] = xz2 + wy2;dst->m[9] = yz2 - wx2;dst->m[10] = 1.0f - xx2 - yy2;dst->m[11] = 0.0f;dst->m[12] = 0.0f;dst->m[13] = 0.0f;dst->m[14] = 0.0f;dst->m[15] = 1.0f;
}

矩阵缩放变换算法

公式如下:

∣ S 1 0 0 0 0 S 2 0 0 0 0 S 3 0 0 0 0 1 ∣ ⋅ { x y z 1 } = { S 1 ⋅ x S 2 ⋅ y S 3 ⋅ z 1 } \left| \begin{matrix} S_1 & 0 & 0 & 0 \\ 0 & S_2 & 0 & 0 \\ 0 & 0 & S_3 &0 \\ 0 & 0 & 0 & 1 \end{matrix} \right| \cdot \left\{ \begin{matrix} x \\ y \\ z \\ 1 \end{matrix} \right\} = \left \{ \begin{matrix} S_1 \cdot x \\ S_2 \cdot y \\ S_3 \cdot z \\ 1 \end{matrix} \right\} ∣ ∣​S1​000​0S2​00​00S3​0​0001​∣ ∣​⋅⎩ ⎨ ⎧​xyz1​⎭ ⎬ ⎫​=⎩ ⎨ ⎧​S1​⋅xS2​⋅yS3​⋅z1​⎭ ⎬ ⎫​

其中S1,S2,S3是放大系数。

cocos2dx中的代码

void Mat4::createScale(const Vec3& scale, Mat4* dst)
{GP_ASSERT(dst);memcpy(dst, &IDENTITY, MATRIX_SIZE);dst->m[0] = scale.x;dst->m[5] = scale.y;dst->m[10] = scale.z;
}void Mat4::createScale(float xScale, float yScale, float zScale, Mat4* dst)
{GP_ASSERT(dst);memcpy(dst, &IDENTITY, MATRIX_SIZE);dst->m[0] = xScale;dst->m[5] = yScale;dst->m[10] = zScale;
}

Cocos2d-x 3D渲染技术 (一)相关推荐

  1. 下一代3d渲染技术,体素光线投射

    原文地址http://www.tomshardware.com/reviews/voxel-ray-casting,2423.html 强烈推荐看原英文,由于本人英语水平有限,对于图形学领悟有限,又借 ...

  2. 3D渲染技术分享:实时3D水面渲染(反射、折射、水深与水岸柔边)

    一.开篇 自从上次写了**<用实时反射Shader增强画面颜值>** 后,不少开发者开始尝试用它来渲染水面,但效果都差强人意. 这是因为,水面除了反射,还有许多细节需要考虑. 在此之前,也 ...

  3. 3D建模和3D渲染技术专题一: 热身篇,光线追踪(path Tracing),环境光阴影(ambient occlusion),焦距效果(effect focus)介绍

    相比大家都看到过美国迪斯尼或者梦工厂制作的一些动画片,其中很多都是使用3D图像技术来实现的,也就是说根本不用使用摄像机就能拍出一部很好的动画片.现在想开个专题主要介绍一些3D建模和3D渲染. 我之前在 ...

  4. 3D渲染技术分享:基于PBR的车漆Shader

    如今,许多曾经应用在游戏开发中的技术开始愈发频繁地在工业和商业领 域出现. 无论是在建筑.医疗.工业制造等高技术密度的行业,还是在零售.导航.人机互动等与普罗大众人间烟火息息相关的领域,即时渲染技术都 ...

  5. 3D渲染技术分享:用实时反射Shader增强画面颜值

    自制Shader免费分享:实时反射技术实现与3D领域中的应用示例 一个离谱的开始 细心的小伙伴可能已经发现了,最近麒麟子关于 3D 图形渲染方面的文章输出比之前多了许多. 灵感来源于生活,却更有可能是 ...

  6. 3D渲染技术分享:3D游戏开发渲染调试高级技巧

    零.本文主要知识点 友情劝退:全文7400+字 如果知识点里没有你想要的,那可以直接拉到底,与评论区大神一战. 最初的计划是想写一篇关于KylinsGraphicsDebugger实现原理的文章,但感 ...

  7. Cocos2d-x 3D渲染技术 (三)

    包围盒算法 说白了就是给物体装进一个盒子里,该盒子可以装下物体.目的是为了进行碰撞检测. 种类: 球状碰撞体 立方体碰撞体 胶囊碰撞体 Mesh碰撞体 实现原理是OBB包围盒. 经常使用的两种碰撞算法 ...

  8. Cocos2d-x 3D渲染技术 (二)

    3D坐标系统 五个空间 要把游戏模型显示到屏幕需要经历五个空间. 局部空间 (Local Space,模型空间) 世界空间 (Wolrd Space,游戏空间) 观察空间 (View Space,视觉 ...

  9. 增强现实和3D渲染技术是如何应用在SAP产品里的

    要获取更多Jerry的原创文章,请关注公众号"汪子熙":

最新文章

  1. 机器学习(十九)——PageRank算法, KNN, loss function详解
  2. 走进C/C++函数的名字改编
  3. 函数计算如何粘合云服务,提供端到端解决方案
  4. 纯C++代码实现将像素矩阵保存为bmp图片
  5. 计算机ppt制作培训心得,ppt培训心得体会总结范文
  6. ibm336服务器显示brd,ibmx3850x5服务器故障BRD报警|升级主板微码
  7. java sql编写教务系统_教务管理系统的设计与实现(SQLServer)
  8. 微信表情包的制作以及50*50像素图片太模糊的处理方法
  9. 咸鱼洽谈(find)咸鱼翻身,只争朝夕,谈谈find这个讨面试官喜欢的命令
  10. python代替mathematica_Mathematica 比起 Python 如今还有什么优势?
  11. 二级菜单原生js实现
  12. 2020寒假【gmoj2417】【Loan Repayment】【二分】
  13. TreeSet()原理及使用
  14. 基于appinventor与EasyDL物体检测API的物体检测app
  15. 区块链学习笔记(2)难度整定,区块形成,区块体,Merkle树,Merkle Proof默克尔证明
  16. PHP7有哪些新特性
  17. MacOS编译LibreCAD
  18. 时序分析(8) -- GARCH(p,q)模型
  19. 如何从Excel表格导入数据批量生成二维码
  20. 一次小米手环BLE通信协议的逆向之旅

热门文章

  1. python练习题回顾
  2. php qq接收不了,PHP-利用curl 与php实现qq挂机遇到不能下线问题
  3. 初次使用git配置以及git如何使用ssh密钥(将ssh密钥添加到github)
  4. voip语音质量测试国际电信联盟标准E-mode
  5. vue px2rem插件的使用
  6. 一份来自新人的自我介绍
  7. Oracle 11c在win10操作系统的安装步骤
  8. 服务器xp系统无法粘贴到本地,win7远程xp不能复制怎么办_win7远程连接XP无法使用复制粘贴功能如何解决-win7之家...
  9. Docker实现自动部署
  10. JavaScript设计模式(10种)