从零开始手敲次世代游戏引擎(序)

大家好。我“正式”从事软件工程师这个职业已经快15年了。至于编程的历史则更长,有20余年了。记忆当中第一次编程的机器里只有ROM BASIC,用“*”打了个金字塔。屏幕是那种单色的cga,只能显示绿色的字符。

因为这样,至今我也喜欢手敲代码。我的意思是,从零开始一个字符一个字符的敲。我觉得这个过程特别有意思,有成就感。

我从小就喜欢科技类的东西,父母是做航天工业的,所以也算有些基因,也有机会较早接触到电脑。十多岁在爸爸的办公室看到了装在屏蔽笼子里的图形工作站,旁边一台绘图仪。好像是德国进口的?反正单位里没几个人懂德语,国家花了大价钱买来,也没啥人会用,就供在那里。后来来了个研究生,外语比较好,把厚厚的说明书研究了半天,总算调出了一个例程,可以控制绘图仪画一张航天飞机模型的线框图。记得绘图仪左边一共有6只水笔,一个固定在横杆上的机器手(夹子),可以沿横杆前后(y方向)移动;同时横杆自体在步进马达控制下可以水平(x方向)移动。换色就是移动到左边换笔,然后在纸上绘图。夹子有落笔和提笔两种动作。

扯得有些远了,但总之从那时开始便对计算机绘图产生了浓厚兴趣。后来又有了游戏机,就觉得更有兴趣了。

然而直到近年有幸进了SIE,其实之前一直没有机会能够从事和游戏开发直接相关的工作。毕业后做了4年GUI,又搞了4年DLNA,1年中医四诊仪,3年视频监控设备,中间还客串了2年市场部,写了个销售制造管理系统,才终于进入了游戏行业。

目前我支持着国内200余家主机游戏开发商的开发项目。同时也和诸如中国传媒大学,上海交通大学等在一起推进游戏开发相关的教育项目。

不过这个专栏是纯粹的个人分享,与我所在团体和公司无任何直接关系。

我计划在这个专栏里通过一系列文章的分享,完成并展现一个手敲版游戏引擎的制作过程。可能的话,还会包括在合适的开发板上全手工建立操作系统(这部分主要是交叉编译,不是从零手敲),并在上面跑起来这个手敲版引擎的过程。引擎的部分首先着重runtime部分,editor等host tools在runtime之后。runtime部分则首先做图形渲染部分,然后逐渐迭代扩充。

工程十分浩大,老实说我也不知道要多少篇文章才能写完。平常也很忙,人也不是很勤快,十年肯定是不够的,慢慢写吧。反正也不是很在乎有没有人看,😄。

好了,这篇就这样吧,算开个头。

(– EOF –)

本作品采用知识共享署名 4.0 国际许可协议进行许可。

在Linux上纯手工建立Win64交叉编译环境

I have made an dockerfile for steps described in this article:
https://github.com/netwarm007/dockerfile-mingw64

因为想要在linux上面编译gimp给win10(64bit)使用,花了好几天时间研究了一下在Linux上面建立Windows 64bit交叉编译环境的方法。

虽然很多Linux发行版提供mingw64的安装包,但为了最大的自由度,我选择了从源代码手工进行建立的方法。过程很苦逼,但是很能学习到一些东西。

一开始我是选用FreeBSD进行搭建的。但由于FreeBSD系统所带make sed等命令均不是gnu版本,中间遇到一些麻烦,所以又换用基于gnu的Ubuntu。这并不是说FreeBSD不能搭建,只是相对麻烦些。

(主要参考文档:MinGW-w64 – for 32 and 64 bit Windows

首先,需要建立一个交叉编译的目录树。参考了crosstool的相关脚本。为了方便,首先导出几个环境变量:

文件名: setbuilddev.sh

#!/usr/local/bin/bash
export PRJROOT=`realpath ~/work/w64`
export TARGET=x86_64-w64-mingw32
export PREFIX=${PRJROOT}/tools
export BUILD=${PRJROOT}/build-tools
export TARGET_PREFIX=${PREFIX}/${TARGET}

然后是生成交叉编译的目录树:

文件名: createdir.sh

#!/usr/local/bin/bash
if [ -d ${PRJROOT} ]; then
DATE=`date +%y%m%d`
mv ${PRJROOT} ${PRJROOT}_${DATE}
fi
mkdir -p ${PRJROOT}
mkdir -p ${PRJROOT}/build-tools ${PRJROOT}/tools ${PRJROOT}/kernel
mkdir -p ${BUILD}/build-binutils ${BUILD}/build-boot-gcc ${BUILD}/build-gcc
mkdir -p ${BUILD}/build-glibc ${BUILD}/build-glibc-headers
mkdir -p ${TARGET_PREFIX}
之后通过下面的命令建立交叉编译的目录结构。
source ./setbuilddev.sh
chmod +x createdir.sh
./createdir.sh
之后就是准备binutils和gcc的源代码。可以利用crosstool提供的源代码,也可以自己去下。我这里为了以后版本更新的方便,以及追踪我自己的变更,采用了git clone方式。由于国外的git仓库速度太慢,我在Git@OSC上面做了一个中转仓库,加速国内访问的速度。
cd $BUILD
git clone https://git.oschina.net/netwarm007/binutils-gdb.git
git clone https://git.oschina.net/netwarm007/gcc.git
这里我首先遇到的一个问题是,gcc.git太大,即使是从Git@OSC进行clone,中间也会出问题。而git clone一旦出问题,不会在本地保留任何东西,下次必须从头再来。通过查阅互联网上的相关资料,最后找到的解决方法是使用–depth这个选项。(如果是用git://或者git+ssh://类型的REPO似乎可以避免这个问题)
首先
git clone –recursive https://git.oschina.net/netwarm007/gcc.git –depth=100
(–recursive选项是因为这个REPO当中含有gmp/mpc/mpfr 3个子模块。如果是直接使用官方的git repo或者源代码包,则需要另外下载这3个模块。具体参见后文。)
然后
git pull –depth=10000
git pull –depth=100000
git pull –unshallow
根据实际的网络情况,可能需要调整–depth的具体数值。
然后开始交叉编译binutils
cd $BUILD/buid-binutils/
../binutils-gdb/configure –target=$TARGET –prefix=$PREFIX –with-sysroot=$PREFIX
make -j4
make install -j4
注意:如果是FreeBSD等BSD系统,需要使用gmake,而不是make
"-j8"选项需要根据实际编译的环境调整。我用的是4核心环境。如果是8核心,需要改为-j8。这个选项是打开多线程,对于最终编译的结果应该没有影响。也可以添加为环境变量:export MAKEOPTS=-j4,这样就不用每次手动指定了。
注意:由于MAKEOPTS的设置,本文之后的make都不再指定-j4。
之后是gcc的交叉编译。但是编译gcc之前,需要安装TARGET环境的头文件。由于本次是采用mingw-w64,那么就要下载安装mingw-64的源代码。同样,首先是git clone获取源代码。(也可以直接下载源代码包)
cd $BUILD
git clone https://git.oschina.net/netwarm007/mingw-w64.git
然后开始安装头文件。首先创建编译用工作目录:(最好不要在源代码目录进行编译,会打乱源代码目录)
mkdir -p $BUILD/build-mingw-w64-header/
cd $BUILD/build-mingw-w64-header/
配置并安装mingw头文件:
../mingw-w64/configure –prefix=$TARGET_PREFIX –without-crt
make install
这里需要特别注意的就是–prefix的指定比较特别。这是因为接下来交叉编译gcc的需要。

不过在此之前,我们需要建几个软link满足gcc的要求:

ln -s $TARGET_PREFIX $PREFIX/mingw
mkdir -p $TARGET_PREFIX/lib
ln -s $TARGET_PREFIX/lib $TARGET_PREFIX/lib64
如果使用的gcc是官方的版本,还需要如下的dependencies:
configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+.
Try the –with-gmp, –with-mpfr and/or –with-mpc options to specify their locations.
注意: --with-gmp, --with-mpfr and/or --with-mpc 这几个选项是用来指定install之后的lib的位置的。不是用来指定源代码的位置的。
因此,我们回到$BUILD目录,获取相关的代码:
cd $BUILD
hg clone  https://gmplib.org/repo/gmp/
git clone https://scm.gforge.inria.fr/anonscm/git/mpc/mpc.git
svn checkout svn://scm.gforge.inria.fr/svn/mpfr/trunk mpfr
然后将这3个目录放在$BUILD/gcc目录的下面。(注意:似乎将一个git clone出来的目录放在另外一个git clone出来的目录里会带来问题。因此,如果gcc目录已经是一个git仓库了,请用
gti archive master | tar -x -C ./gcc/xxx
的方式来将目录放在gcc下面) (注意:这3个组件如果是以源代码的形式和GCC一起编译,必须放在gcc目录下面,并且必须是gmp,mpc,mpfr这样的名字,不能带版本号)
注意gmp目录下面如果没有configure,则需要运行.bootstrap来生成。mpc和mpfr也类似(需要先生成configure)。
接下来我们可以进行gcc的交叉编译了。注意gcc的交叉编译分为两步,第一步只编译编译器本身:

 

cd $BUILD/build-boot-gcc
../gcc/configure –target=${TARGET} –prefix=${PREFIX} –with_sysroot=${PREFIX} –enable-languages=c,c++
make all-gcc
make install-gcc
如果使用master进行编译,有时会遇到错误。
写这篇文章的时候,我这里使用的版本如下:
  • gcc 5.2.0
  • gmp 6.0.0
  • mpc 1.0.3
  • mpfr 3.1.3
注意:如果切换了gcc分支重新编译的时候,需要首先清空build-gcc目录。
现在我们有了交叉gcc了,接下来我们编译C运行时库函数,mingw-crt。
重要: export PATH="$PATH:$PREFIX/bin"
       * 因为从这里起其实已经是交叉编译。要让configure能够找到上面构建的交叉工具 
cd $BUILD/build-mingw-w64-crt
 ../mingw-w64/configure –-host=$TARGET –prefix=$TARGET_PREFIX –without-header –with-sysroot=$TARGET_PREFIX
make
make install
现在我们有了CRT(C语言运行时库)了,可以继续编译交叉GCC相关的库了。
cd $BUILD/build-gcc
../gcc/configure –target=${TARGET} –prefix=${PREFIX} –with_sysroot=${PREFIX} –enable-languages=c,c++
make all
make install
 至此交叉编译器以及相关的头文件、基础库就好了。写一个shell脚本进行交叉编译环境的设定,以供之后交叉编译软件使用。
文件名:setbuilddev_w64.sh
#!/usr/local/bin/bash
export PRJROOT=`realpath ~/work/w64`
export TARGET=x86_64-w64-mingw32
export PREFIX=${PRJROOT}/tools
export BUILD=${PRJROOT}/build-tools
export TARGET_PREFIX=${PREFIX}/${TARGET}
export PATH=${PATH}:${PREFIX}/bin
export PKG_CONFIG_LIBDIR=
export PKG_CONFIG_PATH=$TARGET_PREFIX/lib/pkgconfig
#export LD_LIBRARY_PATH=$TARGET_PREFIX/lib #设置这个会导致某些host工具无法正常运行,所以注释掉。
export C_INCLUDE_PATH=$TARGET_PREFIX/include
export ACLOCAL_FLAGS=”-I $TARGET_PREFIX/share/aclocal”
export CFLAGS=”-I$TARGET_PREFIX/include”
export CPATH=”$TARGET_PREFIX/include”
export LDFLAGS=”-L$TARGET_PREFIX/lib”
好了,大功告成,编译一个hello_world.exe在windows上面跑跑看吧。不仅可以写console程序,还可以写win32程序哦。

Disable Google Fonts

最近突然发现这个网站的访问速度慢了很多。

一开始以为是阿里云不稳定,后来通过浏览器的F12工具抓包,观察到有一个指向Google的请求很长时间没有返回,导致浏览器不渲染网页,从而造成网站访问的迟延。

于是询问度娘,发现了不少类似问题。这个问题是由于WordPress 3.8版本之后的一些主题中使用了Google的Web Font,而从国内访问Google的服务器时好时坏引起的。继续搜索发现有一个名为“Disable Google Fonts”的WP插件,安装完毕以后网站立即又恢复了火箭速度。。。

为什么要Block Google?

2008东京动漫展

 第一次参加这个活动。怕人多一早就去排队,没想到还是排了一公里多。好在队伍行进的速度不算太慢,不到一个小时也就进去了。规模要比东京游戏展小很多,模特也比较少,不过看到各种各样熟悉的卡通形象,还是很开心的。

引用

DSC02105

涂色画制作

涂色画制作