Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

Git Patch使用帮助

发表于 2021-04-28

多人协作开发,需要将别人开发的代码合并。这时使用git patch命令合并是最方便。下面介绍这种方法。

git patch作用

  • 什么是patch? 简单来讲,patch中存储的是你对代码的修改
  • 什么是生成patch? 生成patch就是记录你对代码的修改并将其保存在patch文件中
  • 什么是打patch? 打patch就是将patch文件中对代码的修改,应用到源代码,从而把对代码的修改应用到code中。

git patch用法

生成patch

1
2
3
4
5
6
7
8
$ git format-patch HEAD^    #生成最近的1次commit的patch
$ git format-patch HEAD^^   #生成最近的2次commit的patch
$ git format-patch HEAD^^^   #生成最近的3次commit的patch
$ git format-patch HEAD^^^^   #生成最近的4次commit的patch
$ git format-patch <r1>..<r2> #生成两个commit间的修改的patch(包含两个commit. <r1>和<r2>都是具体的commit号)
$ git format-patch -1 <r1> #生成单个commit的patch
$ git format-patch <r1> #生成某commit以来的修改patch(不包含该commit)
$ git format-patch --root <r1> #生成从根到r1提交的所有patch

应用patch

检查patch/diff是否能正常打入:

1
2
git apply --check 【path/to/xxx.patch】
git apply --check 【path/to/xxx.diff】

打入patch/diff:

1
2
3
git apply 【path/to/xxx.patch】
git apply 【path/to/xxx.diff】
git am 【path/to/xxx.patch】

TortoiseGit patch用法

TortoiseGit是一个Git版本控制客户端,作为Microsoft Windows的外壳扩展实现。它在GNU通用公共许可协议下作为自由软件发布。使用TortoiseGit 的 Create Patch Serial和 Apply Patch Serial两个菜单可以很方便的产生和应用补丁。

参考链接

  1. TortoiseGit,by wikipedia.
  2. 如何用git命令生成Patch和打Patch,by 青山牧云人.
  3. Git 打补丁– patch 和 diff 的使用(详细),by alanwangmodify.

OSG鼠标拾取拖拽物体的原理

发表于 2021-04-13 | 更新于 2021-04-14

在3D世界中,通过鼠标拾取拖拽物体是一个神奇事情,它的具体实现方法如下:

  1. 将鼠标点击视口的二维坐标转换成3D世界中的三维坐标。
  2. 视点出发到鼠标点击位置的可形成一条射线,在场景节点树上遍历,查找与射线相交的节点。
  3. 获得拾取节点与视点之间距离,从而计算得到鼠标释放时拾取节点的位置,平移拾取节点到目标位置。

2D坐标转3D坐标参考

1
2
3
4
5
6
7
8
9
10
11
12
osg::Vec3 screenToWorld(osgViewer::Viewer* viewer,double dx,double dy)
{
osg::Camera *camera = viewer->getCamera();
osg::Matrix viewMat = camera->getViewMatrix(); //获取当前视图矩阵
osg::Matrix projMat = camera->getProjectionMatrix();//获取投影矩阵
osg::Matrix windMat = camera->getViewport()->computeWindowMatrix();//获取窗口矩阵
osg::Matrix MVPW = viewMat * projMat *windMat; //视图-》投影-》窗口变换

osg::Matrix inverseMVPW = osg::Matrix::inverse(MVPW);
osg::Vec3 mouseWorld = osg::Vec3(dx, dy, 0) * inverseMVPW;
return mouseWorld;
}

获取拾取节点代码参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//参数说明:firstPos:是当前摄像机的位置。endPos:为偏移坐标值,eye + curRayLineDir*100
//curRayLineDir = mouseWorldPos(屏幕点转三维点使用上面的函数) - eye;
//curRayLineDir.normallize();
void CIntersectEventHandler::rayLinePick(const osg::Vec3& firstPos,const osg::Vec3& endPos)
{
osg::ref_ptr<osgUtil::LineSegmentIntersector> lineSegmentIntesector = \
new osgUtil::LineSegmentIntersector(firstPos,endPos);
osgUtil::IntersectionVisitor intersectionVisitor(lineSegmentIntesector);

m_matNode->accept(intersectionVisitor);//m_matNode为你拾取的物体

osgUtil::LineSegmentIntersector::Intersections intersections;
if (lineSegmentIntesector->containsIntersections())
{
intersections = lineSegmentIntesector->getIntersections();
for(auto iter = intersections.begin(); iter != intersections.end(); ++iter)
{
osg::NodePath nodePath = iter->nodePath;
m_pickPoint = iter->getWorldIntersectPoint();
for(int i=0; i<nodePath.size(); ++i)
{
m_pickObj = dynamic_cast<osg::MatrixTransform*>(nodePath[i]);//拾取到的node
}
}
}
}

拖拽物体参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//我是在osgGA::GUIEventAdapter::DRAG进行拖拽的功能
if(m_pickObj && m_bLeftMouseBtn)//这个布尔值就是晓得鼠标的左键是否按下了。
{
//获取当前的摄像机的位置
osg::Vec3 eye = viewer->getCamera()->getInverseViewMatrix().getTrans();
//计算当前摄像机与pick到的模型之间的距离是多少
osg::Vec3 offset = m_pickPoint - eye;
int dist = offset.length();
//计算当前的鼠标屏幕点映射到三维中的值
osg::Vec3 mouseWorldPos = screenToWorld(viewer,ea.getX(),ea.getY());
//计算当前鼠标三维点与摄像机的方向
osg::Vec3 rayDir = mouseWorldPos - eye;
rayDir.normalize();
//最后计算物体拖拽时最终的世界位置
osg::Vec3 curPos = eye + rayDir*dist;
m_pickObj->setMatrix(osg::Matrix::translate(curPos));
}

参考链接

  1. OSG实现鼠标拖拽物体,by 码农家园.
  2. OSG拾取对应的实体,by 成魔的羔羊.

FlightGear的Nasal脚本语言学习笔记

发表于 2021-03-30 | 更新于 2021-04-17

Nasal是FlightGear内建的脚本语言。 它最初是由安迪·罗斯(Andy Ross)为个人项目编写和开发的,于2003年11月被集成到FlightGear中,并且从那时起一直在不断地开发,改进和完善。 随着时间的流逝,它可能已成为FlightGear的最强大功能,并已用于创建各种各样的系统,从野火到控制显示单元。

在FlightGear中,Nasal支持读取和写入内部属性,通过扩展功能访问内部数据,创建GUI对话框等等。注意到Nasal是一种与JavaScript语法类似的脚本语言,但是它能够与FlightGear之间进行双向交互,实现非常强大的功能,这主要是通过CppBind实现的。

创建可点击的面板

FlightGear中创建可点击的面板有两种方法:

  • 热点区域:在某个位置创建可点击表面
  • 拾取:使一整个对象可以被点击

可点击面板的测试

使用“Ctrl+C”可显示所有可点击的面板对象。

属性浏览器

属性树是FlightGear的神经系统,连接着FlightGear的各个子系统,是各个子系统之间交互的桥梁。因此,需要属性浏览器窗口查看各个属性的变化。打开属性浏览器的方式有两种:

  • 通过按键 Ctrl+/ 打开属性浏览器
  • 通过主菜单 Debug > Browse Internal Properties 打开属性浏览器

详细模式

在属性浏览器窗口中,通过按键 Ctrl+. 可用来切换属性浏览器的详细模式(Verbose mode)。在详细模式下,可获得属性的额外信息,例如属性的类型、属性上侦听器的数量等。

参考链接

  1. Nasal scripting language,by flightgear.
  2. Nasal library,by flightgear.
  3. Bindings,by flightgear.
  4. Category:Howto,by flightgear.
  5. Howto:Animate models,by flightgear.
  6. Howto:Make a clickable panel,by flightgear.
  7. Howto:Creating 3D instruments,by flightgear.
  8. Property tree,by flightgear.
  9. PropertyList XML files,by flightgear.
  10. Property browser,by flightgear.
  11. Effect Framework,by flightgear.
  12. Canvas EFIS Framework,by flightgear.
  13. Nasal/CppBind,by flightgear.
  14. Howto:Extend Nasal,by flightgear.
  15. Canvas ND Framework,by flightgear.

Word文档压缩方法

发表于 2021-03-30

编写完一个大型Word文档之后,发现文档大小远远超过预期。那么如何压缩word文档,使其满足我们的要求呢?

首先要了解大型word文档”虚胖”的原因,然后我们才能针对性性的压缩。大型word文档”虚胖”的原因具体如下:

  1. 文档中有大量图片
  2. 文档中有Visio图、公式
  3. 文档中有大量交叉引用
  4. 文档在编辑过程中保存了大量无关内容

针对原因1,解决方案是保存文档时设置压缩图片的选项为电子邮件”96ppi”。
针对原因2和原因3,解决方案是全选word文档,使用快捷键“ctrl+shift+f9”,将会去除引用,将Visio图和公式转换成图片。
针对原因4,解决方案是将word文档内容全选,复制到新的word文档。

参考链接

  1. word中VISIO图批量转为图片格式,by baidu.

数据流分析

发表于 2021-03-29

数据流分析 是一种用于收集计算机程序在不同点计算的值的信息的技术。

基本原理

数据流分析试图获得程序中每一点的特定信息。通常,在基本块的界限内就可以获得这些信息,因为很容易计算基本块中的信息。在前向流分析(forward flow analysis)中,一个块的结束状态是这个块起始状态的一个函数。函数由块内的语句的影响信息组成。一个块的开始状态是它的前驱的结束状态的函数。这就产生了一系列的数据流方程:

对于每一个块$b:$

$$ out_b = trans_{b}(in_b) $$
$$ in_b = join_{p \in pred_b}(out_p) $$

在这里,$trans_b$ 是块 $b$ 的 转移函数。它作用于入口状态$in_b$,并产生出口状态$out_b$。连接运算符 $join$ 将块 $b$ 的前驱节点 $p \in pred_b$ 的出口状态联合起来,产生入口状态 $b$。

在求解这一系列方程之后,块的入口和出口状态可以被用来获得程序在块内的属性。每条语句的转移函数可以被分别的用于获得在一个基本块内的某一点的信息。

参考链接

  1. 数据流分析,by wikipedia.

OSG学习笔记

发表于 2021-03-17 | 更新于 2022-12-11

OpenSceneGraph是一个开源3D图形应用程序编程接口,应用程序开发人员在诸如视觉模拟,计算机游戏,虚拟现实,科学可视化和建模等领域中使用该接口。

OSG 编译运行问题

OSG指出GL版本问题

CMake设置了GL3的开关,结果编译完后,好多例子无法正常运行。

原因:GL3对GL1、GL2不兼容

解决办法:去掉GL3选项

GL3(3.3),属于OpenGL的高版本驱动所支持的接口,需要完全使用可编程管线.

不开启GL3设置,其实也可以使用GL3的特性,论坛作者提到osg使用了兼容模式,编写OpenGL3.3以上着色器,配置兼容模式即可使用。

获取OSG指出的OpengGL版本,可参考How to obtain OpenGL version from within OpenSceneGraph。

OSG运行的坑:WINGDIAPI(GL.h)

在VS运行OSG程序时,要将预处理器设置为WIN32,否则GL.h头文件会报错。

osg键盘事件不响应的解决方法

1、换输入法为英文状态
2、(若1不行)换键盘为美式键盘

osgQt键盘事件不响应的解决方法

请参考osg嵌入Qt后,键盘响应以及程序退出崩溃问题解决。

OSG开发技巧

OpenGL中的功能与OSG对应功能

OSG 调试

打开cmd,输入如下命令:

1
2
SET OSG_NOTIFY_LEVEL=DEBUG
osgviewer cow.osgt

坐标系

OSG中采用的X轴正方向向右,Y轴正方向朝里,Z轴正方向向上。

OpenGL中采用的X轴正方向向右,Y轴正方向朝上,Z轴正方向朝外。

OSG与OpenGL坐标系

图1 OSG与OpenGL坐标系

显示模型坐标轴

使用如下命令显示模型坐标轴:

1
osgviewer cessna.osgt axes.osgt

OSG相机默认视角

osg::Camare的默认姿态:

  • 位置在 0,0,0
  • 姿态是:向下看(Z轴负向 0,0,-1)
  • 头向前(Y轴正向 0,1,0,也就是说相机是正着的)

OSG渲染状态管理

OpenGL是一个状态机,在OpenGL中如果设置一种状态(比如设置当前的绘制颜色:glColor,那么实际上是设置了OpenGL颜色绘制状态为某种颜色,如果后续没有调用glColor去修改颜色,那么之后所有绘制的对象都使用之前设置的颜色。),在没有修改它的时候,该状态就会一直保持。在OpenGL使用中的状态有以下两种方式:

  • 仅仅通过glEnable和glDisable开启和关闭状态
    这里面也有两种不同的取值:

    • 1.1 不涉及和其他状态相关,比如GL_DITHER、GL_POINT_SPRITE等;
    • 1.2 涉及和其他状态的联动,比如GL_ALPHA_TEST、GL_BLEND等,需要使用glEnable开启状态
  • 和1.2种的某种状态对应,但是需要设置状态的值(比如glAlphaFunc、glBlendFunc)

在OSG中对OpenGL的状态进行了封装,在OSG中称第一种情形为Mode(模式),称第二种情况为Attribute(属性),使用osg::StateAttribute来封装OpenGL的状态。

在OSG中涉及到状态管理的类有3个,分别是 osg::State, osg::StateSet, osg::StateAttribute。

OSG渲染

OSG可以使得绘制遍历,也就是将数据传送给OpenGL管线,在一个单独的线程中运行。他必须与每一帧中的其他绘制遍历相同步,但是绘制遍历的部分可以与来自下一帧的更新遍历相重叠,从而改善渲染效率并减少帧延迟。这意味着osgViewer::Viewer的frame()方法会在绘制工作依然处于活动状态时返回。那么更新回调中的数据变化也许会与未完成的渲染操作相冲突,从而导致不可预期的行为,甚至崩溃。

OSG在setDataVariance()方法中提供了解决方法,该方法属于osg::Object类,这是所有场景对象的基类。这可以设置为三个枚举值之一:UNSPECIFIED(默认),STATIC与DYNAMIC。场景图中的DYNAMIC对象必须在绘制遍历的开始进行处理。也就是,渲染后端应确保所有节点以及被指定为DYNAMIC的场景对象在下一帧的更新与裁剪遍历开始之前已完成绘制。然而,STATIC对象,在更新与绘制过程中会保持不变,从而会被稍后渲染且不会阻塞帧速率。

Object::DataVariance

要设置一个Object 对象的数据变量,可以调用setDataVariance()并设置输入参数为Object::DataVariance 枚举量。初始状态下,变度的值是UNSPECIFIED。用户程序可以将数据变度更改为STATIC 或者DYNAMIC。OSG 将确保绘制遍历在所有的DYNAMIC 节点和数据处理完成后才会返回。

场景数据动态更新的核心就是设置数据变度属性DataVariance,它决定了OSG在多线程渲染的过程中的执行策略:只有所有DYNAMIC属性的对象被渲染完毕之后,OSG才会开始执行下一帧的用户更新操作;这样有效地可以避免数据的过快更新造成当前的渲染动作出错,以致系统崩溃。

OSG绘制几何体

默认情况下,OSG使用顶点数组与显示列表来管理与渲染几何。然而,这会依据不同的数据类型与渲染策略而发生变化。

OSG矩阵相乘

OSG使用行向量与行为主矩阵在右侧原则(right-hand rule)下来执行前相乘(vectormatrix)。然而,OpenGL使用列为主矩阵与列向量来执行后相乘(matrixvector)。

OSG节点的增加,删除,隐藏和开关

osg::Switch 从osg::Group继承而来,是一个管理类,除了可以当成osg::Group使用外,它还可以控制子类的显示与隐藏, 这种隐藏是不耗费内存的,与 SetNodeMask对比有明显的优势,SetNodeMask只是隐藏了结点,但结点仍被绘制。

OSG纹理

osg::Texture2D类要求纹理坐标正规化为[0,1],否则他会使用纹理封装来处理多余的部分。他会检测纹理的维度在尺寸上是否全部为2的幂次,例如64x64或256x512,并且在默认情况下会使用OpenGL的gluScaleImage()函数在内部缩放不是2的幂次的图像,这对于读取任意的图像非常方便,但是需要更多的系统时间并会占用较大的图形内存尺寸。

OSG状态

正常情况下,节点的状态集将会影响当前节点及其子节点。例如,节点transformation1的osg::PolygonMode属性将会使得其所有子节点显示为轮廓图。然而,子节点的状态集可以覆盖父节点的状态集,也就是,渲染状态将会由父节点继承,除非子节点改变这一行为。

非正常情况下,父节点可以使用osg::StateAttribute::OVERRIDE标记,以强制其所有的子节点继承其属性或模式。子节点也可以使用osg::StateAttribute::PROTECTED标记,来改变其继承性,从而会导致不同的结果。

OSG Viewer

osgViewer::View类是osgViewer::Viewer类的超类。他接受设置根节点作为场景数据,并添加相机操作器与事件处理器来使用用户事件。osgViewer::View与osgViewer::Viewer之间的区别在于前者不能被直接用作单个查看器,也就是,他没有run()或frame()方法。

1
2
osgViewer::CompositeViewer multiviewer;
multiviewer.addView( view );

OSG事件响应

可参考osg demo12 响应鼠标事件

OSG多个着色器

当OSG的父节点附加一个着色器,子节点附加另一个着色器会发生什么事情?

答案是子节点渲染时,其自身着色器会生效,而不会运行父节点着色器。

3D模型转换

osgconv是一种非常有用的的工具来读取标准的3D格式,如OpenFlight,3DS,Alias Wavefront
(OBJ) etc,并且可以将它们转换为一种OSG所支持的格式,如OSG中的ASCII格式的.osg,二进制格式的.ive。
在程序运行的默认情况下,优化导入的场景图,将形成的这样结果:场景图读取的数据量将会更少且速度会更
快。尤其值得指出的是,.ive格式的的文件,快速装载数据的能力使它非常适合数据页和大型的数据库。

使用方法如下:

1
2
osgconv cow.obj cow.ive
osgconv --compressed cow.obj cow.ive

参考链接

  1. OpenSceneGraph,by wikipedia.
  2. OSG渲染引擎架构——整体认识,by wikipedia.
  3. OSG渲染状态管理,by csxiaoshui.
  4. OSG中的DataVariance,by codetd.
  5. OpenGL中的功能与OSG对应功能,by 南水之源.
  6. OpenGL——颜色混合 glBlendFunc函数,by Timidkid.
  7. OpenGL Display List学习,by Antplay.
  8. osg学习(五十二)加载的牛模型cow.osg没有纹理 黑色,by hankern.
  9. OSG仿真案例(4)——创建烟雾粒子效果,by rexinx.
  10. OSG中的DataVariance,by sunflower_cs.
  11. OSG渲染状态管理,by csxiaoshui.
  12. OpenSceneGraph plugin not included in Conan?,by stackoverflow.
  13. osg示例解析之osgparticle(1) ,by csxiaoshui.
  14. 欢迎来到OpenGL的世界,by learnopengl.
  15. OSG调试经验,by 醉逍遥_祥.
  16. OSG使用GLSL各个版本例子,by 封狼居胥_COU.
  17. OSG运行的坑:WINGDIAPI(GL.h),by lessssssss.
  18. OSG 3.6.3 版本编译一些问题,by longlongway2012.
  19. 01-01-osg下GL3环境搭建,by Longlongwaytogo.
  20. OSG报警特效学习总结 ,by JosephDcc.
  21. OSG 绘制Geometry使用,by jdq0603.
  22. OSG三维渲染引擎–OSG渲染引擎中坐标系,by 苏黎.
  23. How to obtain OpenGL version from within OpenSceneGraph,by Victoria Rudakova.
  24. OSG运行的坑:WINGDIAPI(GL.h),by lessssssss.
  25. OSG可绘制体Drawable,by csxiaoshui.
  26. OSG 渲染剖析 之 Geometry 的 VBO生成,by Night_Aurora.
  27. osg绘制四边形,by mob60475700473b.
  28. osg setRenderBinDetails 使用,by longlongway2012.
  29. ogs节点的增加,删除,隐藏和开关,by 先锋小牛.
  30. osg demo12 响应鼠标事件,by analyst_yuci.
  31. [osg-users] Multiple Shaders,by J. Brent Spears.
  32. OSG 中默认的 Shader,by 洛克人杰洛.
  33. osgconv使用指南(转),by 3D入魔.
  34. osg嵌入Qt后,键盘响应以及程序退出崩溃问题解决,by 程序开发园.
  35. OSG相机,by wb175208.

OpenGL学习笔记

发表于 2021-03-13 | 更新于 2022-11-27

OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来从简单的图形比特绘制复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。

核心模式与立即渲染模式

早期的OpenGL使用立即渲染模式(Immediate mode,也就是固定渲染管线),这个模式下绘制图形很方便。OpenGL的大多数功能都被库隐藏起来,开发者很少有控制OpenGL如何进行计算的自由。而开发者迫切希望能有更多的灵活性。随着时间推移,规范越来越灵活,开发者对绘图细节有了更多的掌控。立即渲染模式确实容易使用和理解,但是效率太低。因此从OpenGL3.2开始,规范文档开始废弃立即渲染模式,并鼓励开发者在OpenGL的核心模式(Core-profile)下进行开发,这个分支的规范完全移除了旧的特性。

当使用OpenGL的核心模式时,OpenGL迫使我们使用现代的函数。当我们试图使用一个已废弃的函数时,OpenGL会抛出一个错误并终止绘图。现代函数的优势是更高的灵活性和效率,然而也更难于学习。立即渲染模式从OpenGL实际运作中抽象掉了很多细节,因此它在易于学习的同时,也很难让人去把握OpenGL具体是如何运作的。现代函数要求使用者真正理解OpenGL和图形编程,它有一些难度,然而提供了更多的灵活性,更高的效率,更重要的是可以更深入的理解图形编程。

着色器

着色器(Shader)是运行在GPU上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。从基本意义上来说,着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立的程序,因为它们之间不能相互通信;它们之间唯一的沟通只有通过输入和输出。

GPU渲染管线

图1 GPU渲染管线

着色器分类

每个着色器使用这两个关键字设定输入和输出,只要一个输出变量与下一个着色器阶段的输入匹配,它就会传递下去。但在顶点和片段着色器中会有点不同。

顶点着色器

用来描述顶点属性(如位置、颜色等)的程序。顶点是二维或者三维空间中的一个点,比如二维或者三维图形的端点或交点。

1
2
3
4
5
6
//顶点着色器程序
var VSHADER_SCOURCE =
'void main() {\n' +
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' +
' gl_PointSize = 5.0;\n'+
'}\n';

细分着色器

曲面细分着色器包含细分控制着色器 (Tessellation Control Shader / Hull Shader) 和细分计算着色器 (Tessellation Evaluation Shader / Domain Shader) 。在这个阶段可以操作三角形 (tri patch) 、四边形 (quad patch) 或者线段 (isoline) 等 patch 。

低精度网格、置换贴图和法线贴图等,在曲面细分着色器 (Tessellation Shader) 中,使用合适的细分算法,可以生成高精度网格,从而提高游戏画面的细节。

几何着色器

几何着色器(Geometry Shader)是由第四代显卡着色器架构 Shader Model 4 正式引入的第三个着色器,属于渲染管线的一个可选阶段,位于曲面细分(Tessellation)和光栅化(Rasterization)之间。顶点着色器以顶点数据作为输入数据,而几何着色器则以完整的图元(Primitive)作为输入数据。例如,以三角形的三个顶点作为输入,然后输出对应的图元。与顶点着色器不能销毁或创建顶点不同,几何着色器的主要亮点就是可以创建或销毁几何图元,此功能让GPU可以实现一些有趣的效果。例如,根据输入图元类型扩展为一个或更多其他类型的图元,或者不输出任何图元。需要注意的是,几何着色器的输出图元不一定和输入图元相同。几何着色器的一个拿手好戏就是将一个点扩展为一个四边形(即两个三角形)。

1
2
3
4
5
6
7
8
9
10
11
12
13
#version 330 core
layout (points) in;
layout (line_strip, max_vertices = 2) out;

void main() {
gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0);
EmitVertex();

gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);
EmitVertex();

EndPrimitive();
}

片元着色器

进行逐片元处理过程如光照的程序。片元可理解为像素。

1
2
3
4
5
//片元着色器程序
var FSHADER_SCOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';

变量

attribute变量

attribute变量是只能在vertex shader中使用的变量。(它不能在fragment shader中声明attribute变量,也不能被fragment shader中使用)

一般用attribute变量来表示一些顶点的数据,如:顶点坐标,法线,纹理坐标,顶点颜色等。

uniform变量

Uniform变量简单理解就是一个GLSL shader中的全局常量,可以随意在任意shader(vertex shader, geometry shader, or fragment shader)访问,不同的shader中uniform是一起链接的,初始化之后,不能修改其值,否则会引起编译错误。

varying变量

varying变量是vertex和fragment shader之间做数据传递用的。一般vertex shader修改varying变量的值,然后fragment shader使用该varying变量的值。因此varying变量在vertex和fragment shader二者之间的声明必须是一致的。application不能使用此变量。

坐标系

OSG中采用的X轴正方向向右,Y轴正方向朝里,Z轴正方向向上。

OpenGL中采用的X轴正方向向右,Y轴正方向朝上,Z轴正方向朝外。

OSG与OpenGL坐标系

图2 OSG与OpenGL坐标系

参考链接

  1. OpenGL,by wikipedia.
  2. LearnOpenGL,by Joey de Vries.
  3. 着色器,by wikipedia.
  4. 几何着色器,by 学无止境.
  5. 曲面细分着色器 1 简介,by MultivacX.
  6. Rendering Pipeline Overview,by opengl homepage.
  7. OpenGL 4.0的Tessellation Shader(细分曲面着色器),by zenny_chen.
  8. OpenGL基础 - 统一变量Uniform,by 靖空间.
  9. 点到平面的距离公式,by 翰墨小生.
  10. OSG 碰撞检测之多面体求交器代码解读(PloytopeIntersector),by 风一样消逝的青春.
  11. OpenGL(八) 显示列表,by -牧野-.
  12. OSG三维渲染引擎–OSG渲染引擎中坐标系,by 苏黎.
  13. OpenGL学习笔记(12)基本光照,by Clingingboy.
  14. GLSL 三种变量类型(uniform,attribute和varying)理解,by wo不懂.
  15. OpenGL之glPolygonMode函数的用法,by 草上爬_.

doxygen编译安装与文档生成

发表于 2021-03-09 | 更新于 2021-03-10

Doxygen是一个适用于C++、C、Java、Objective-C、Python、IDL(CORBA和Microsoft flavors)、Fortran、VHDL、PHP、C#和D语言的文档生成器。它可以在大多数类Unix操作系统、macOS以及Microsoft Windows上运行。由于该文档是直接写在源代码中的,因此比较容易保持更新。Doxygen可以交叉引用和源代码,使文件的读者可以很容易地引用实际的源代码。

编译安装

Windows平台

Windows平台编译安装doxygen请参考链接Compiling from source on Windows。

文档生成

请参考Doxygen快速入门。

参考链接

  1. Compiling from source on Windows,by doxygen.
  2. Doxygen,by wikipedia.
  3. Doxygen文档生成工具教程,by chend0316.
  4. Doxygen快速入门,by 路明.
  5. User:Callahanp/Flightgear and Simgear Code/Doxygen,by flightgear wiki.

源代码分析的方法

发表于 2021-03-01 | 更新于 2021-03-02

源码分析的目的是讲解代码要解决什么问题、代码如何解决问题的以及代码为什么要这么解决问题。

源码分析的入手点是软件而不是源代码。软件( Software )是一个宽泛的概念,包括应用程序、工具箱和框架等等。软件可以说是由代码组成的,那么我们强调入手点是软件而不是源代码的原因是什么呢?

源码分析从源代码入手,就容易落入具体实现的窠臼当中;而代码构成的软件整体,有其被创造的背景、要解决的问题、演进过程中面临的困难和决策,以及最终所为用户认知的形态。源码分析从软件整体入手,才能够脱离技术人员对技术本身的痴迷的影响,从务实的角度讲解代码要解决什么问题、代码如何解决问题的以及代码为什么要这么解决问题。

《深入理解 Spring MVC 源代码》的讲解按照目录分成三个部分。

第一部分主要从使用的角度入手,由开发者最熟悉的功能切入,讲解了基本组件包括控制器、模型和视图在抽象层面上是如何被支持的。在此基础上对 MVC 模型最承担逻辑的控制器展开了详细的介绍,尤其是平时容易被终端开发者忽略的请求是如何进入框架和流程以及返回值是如何交付给请求方的。最后用简短的篇幅简略地介绍了 WebFlux 的发展趋势和一些常见的配置项。

第二部分接着从源码切入,首先介绍了源码阅读的一些技术技巧,再对 Spring MVC 框架的启动、MVC 框架请求分发的核心 DispatcherServlet 类的功能、RequestMapping 的查找原理和请求处理方法的执行过程一一进行具体的介绍。每个细节部分也是按照这种主题加解决方法的模式,先抛出一个问题,抽象地讨论解决思路,再结合代码讲解关键细节,最后简略地做完整性补充和扩展讨论。

第三部分可以单独拆开来,是在完成了源码分析以后以一个常见的基于 Spring MVC 实现微信公众号快速开发框架的例子来介绍 Spring MVC 的实用过程。通过分析时下热点的具体实例,可以让读者清晰的看到前面所讲的知识点在实践中到底是怎么被运用的,哪些一定会涉及且常常会被实现考虑在内,哪些是在哪种特定情况下会涉及的,以及哪些是平常看不到的或者不需要重点钻研的。

参考链接

  1. 源码分析怎么做?, by tison.
  2. 程序员阅读源码是一种什么心态?源码对编程意义何在?如何才能更好阅读代码?,by zhihu.

JavaScript从字符串中创建函数的方法

发表于 2021-02-26

以下链接中提供了四种JavaScript从字符串中创建函数的方法,可以学习以下。

Is there a way to create a function from a string with javascript?

参考链接

  1. Is there a way to create a function from a string with javascript?,by phnah.
上一页1…232425…53下一页

Jack Huang

521 日志
67 标签
© 2025 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse