Posts

Cocos2d-x之lua核心编程(第二版)》示例代码注释详解 2

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com ##元表的__index方法和__newindex方法 ###1 使用__index方法的代码: --[[ Lua中访问table的元素是先通过__index元方法来查找是否有这个函数,如果没有则返回nil。可以通过改变__index元方法,能够 改变检索之后的结果。__index的值可以直接是一个table,可以是一个function。如果是table则以该table作为索引进行查询, 如果是function,则以table和缺少的table的元素键值的key为参数、 --]] Window = {} Window.mt = {} Window.prototype = {x = 0, y = 0, width=100, height = 100} --[[ 参数1是table,参数2是key,这是固定的格式 --]] Window.mt.__index = function(table, key) return Window.prototype[key] end function Window.new(t) setmetatable(t, Window.mt) -- 设置某个表t的元表为Window.mt return t end -- 测试 t = {x = 10, y = 20} w = Window.new(t) --[[ 表w就是表t,并且t的元表就是Window.mt。本来表t是没有“height”这一个元素项,但因为t指定了元表为Window.mt。 而Window.mt又对元方法__index进行了改写,所以t.height就是Window.prototype.width。如果t本身已经有"height"的话 那么t.height就不是Window.prototype.width了。 --]] print(w.height) ###2 使用了__newindex方法的代码 Window = {} Window.

Cocos2d-x之lua核心编程(第二版)》示例代码注释详解 1

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com ##用元表针对一个table实现+操作 Set = {} -- 首先声明一个名字为"Set"的表,这个Set表,将会作为一个“类”。我们称之为“Set类” Set.mt = {} --[[为了避免命名空间污染,在Set表内部定义一个名为“mt”;类型为表的元素项。这个mt表将作为“表征Set类 的实例对象的表”的元表--]] --[[ Set表内部定义一个名为new,类型为函数的元素项。这个函数用来生一个“表征Set类的实例对象的表”。 从实现功能来看。这个函数类似于C++,Java中的 --]] function Set.new(t) local set = {} -- 生成一个表set,这个set表就等价于Set类的一个对象实例 Set.mt.__add = Set.union -- 表Set.mt的元方法__add就是类Set的union方法 setmetatable(set, Set.mt) -- 指定表set的的元表为Set.mt for i, v in ipairs(t) do -- 遍历传进来的table类型的参数t的每一项元素,然后将t的每一项元素的实值, set[v] = true -- 作为set表的键值 end return set -- 返回表set,即返回Set类的一个对象实例 end -- 合并两个集合a和b并且形成一个新Set对象 function Set.union(a, b) local res = Set.new() -- k short for key for k in pairs(a) do -- 遍历参数a的每一个键值,从new方法可以看到,这个a的键值就是new方法的参数t的实值 res[k] = true end for k in pairs(b) do -- 遍历参数b的每一个键值,从new方法可以看到,这个b的键值就是new方法的参数t的实值 res[k] = true end return res -- 完成两个循环之后,res表中就已经含有a和b的所有键值了。等同于合并了两个集合 end -- 把某一个Set对象格式化成字符串并返回 function Set.

3转2时如何设置摄像机角度以实现isometric渲染效果

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 原文地址: 问:应该如何在 3DS Max 中设置摄像机的观察角度,使得渲染出来的 2D 图是一个 isometric 效果。特别地应该如何获取到渲染出来的图像的精确高宽值。当我们想渲染出来的图的高宽比是 1:2 的时候,该如何设置摄像机的位置,设置摄像机的观察角度? 答:1:如果想渲染出来的图的高宽比是 1:2 的话,这种投影其实不是严格的 isometric(等轴侧)投影。而是类似于 dimetric(正二测,两等角)投影。这种投影的特点便是三个轴中的水平两个轴是按照透视法缩短了。垂直的那个轴则稍微地比按透视法缩短的更为剪短了一点。 Isometric(等轴侧) 投影则是三个轴都是按相等的比例透视缩短的。当使用等轴侧投影的时候,一个轴对齐的菱形将会被投影到水平面上。并且这个菱形的宽高比为:1.732:1 。如下图所示: 在上图中,如果使用宽高比为 2:1 的正二测投影的话。则摄像机俯视水平面的观察角度应该为 30°。如果使用真正的等侧轴投影的话。则摄像机俯视水平面的观察角度应该为 35.264 度。在这里,摄像机的观察角度 A 和投影得到的菱形的宽高比 R 之间的关系是: sin(A) = R 2: 在渲染时,还必须确保渲染用的摄像机,是使用了正交投影的模式。 扩展阅读: Axonometric projection Isometric view setup Isometric View and Isometric Projection

理解高动态范围光

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 现在大部分图形程序员(包括我)可能是从directxsdk处接触到这个概念并开始学习。DirectX SDK中的示例demo较为清晰地展示了一个完整的HDR技术所要采用的流程,如下: 在 float render target 上去渲染当前的场景。 使用 RGBM , LogLuv 等编码方式来节省所需的内存和带宽 通过 down sample 去计算场景亮度 根据亮度对场景做一个 矫正(tone mapping) 最后输出到一个 rgb8 的 render target 上 上面的流程的四个步骤就展示了四个高大上的概念,我们先一一弄懂这些基础概念,再进一步分析。 1 float render target 首先是float render target。render target(以下简称RT)这个概念就不在此详细描述了,这个概念都还没弄懂的话需要先放下这篇文章,先夯实基础再说。RT可以理解为一系列的像素点的集合。在计算机中自然需要用一个一个字节去表示像素点的RGBA信息。最常见的是使用一个字节去表示像素点的一个颜色分量。这样子表示一个像素点则需要四个字节共32位。但一个字节表示一个颜色分量,比如Red分量的话,最多就只能表示256阶的信息。在很多时候,尤其是在处理我们的HDR信息的时候,256阶是远远不够用。所以我们要采用32位或者更高精度的浮点数去表示每一位颜色分量。float render target正是表示这一个概念。 1.1 RGBM RGBM是一种颜色编码方式,如上所述,为了解决这个精度不足以存储亮度范围信息的问题,我们可以创建一个精度更高的buffer,以扩展之前的那个限定在[0,1]取值域的取值范围,从而使得我们可以在RT上渲染一个更高的亮度范围的画面效果。但使用高精度的buffer则带来另一个问题:即需要更高的内存存储空间和更高的带宽,并且有些渲染硬件无法以操作8位精度的buffer的速度去操作16位浮点数的buffer。因此为了解决这个问题,我们需要采用一种编码方法将这些颜色数据编码成一个能以8位颜色分量的存储的数据。编码方式有多种,例如RGBM编码,LogLuv编码,等等。假如有一个给定的包含了RGB颜色分量的颜色值C,将其编码成一个含有RGBM四个分量的颜色值的步骤是: 定义一个"最大范围值",假定为变量MaxRange 取得C的RGB分量中最大的那个值。将这个最大值赋值给变量maxRGB。 用maxRGB除以MaxRange,得到商,将这个商赋值给变量M 用M乘以255得到结果值之后,取得大于这个结果值的最小整数,然后再将这个最小值除以255之后,再赋值给变量M 最后,用C的各个颜色分量,除以M和MaxRange的乘积,作为最终结果颜色的RGB分量,M就作为最后一个分量。 这些步骤写成shader代码如下: float MaxRange = 8; float4 EncodeRGBM(float3 rgb) { float maxRGB = max(rgb.x,max(rgb.g,rgb.b)); float M = maxRGB / MaxRange; M = ceil(M * 255.0) / 255.

一分钟搞定boost库编译

假定已经从www.boost.org下载了最新的boost安装包,以boost1.39.0为例: 把压缩包解压到某目录,比如E:\sdk下,这时候,将得到目录:E:\sdk\boost_1_39_0在此目录下,将有一个子目录boost,里面就是所有的boost内容。 进入 E:\sdk\boost_1_39_0\tools\jam\src 目录,点击 build.bat 文件,将执行 bjam.exe 文件的构建,构建完毕后,将生成E:\sdk\boost_1_39_0\tools\jam\src\bin.ntx86目录。 bjam.exe 就在此目录下。 将 bjam.exe 拷贝到E:\sdk\boost_1_39_0下,在在系统菜单中,点出“运行”对话框,执行cmd命令,调出控制台窗口,然后把当前目录定位到E:\sdk\boost_1_39_0。 输入如下命令: bjam stage --toolset=msvc-8.0 link=shared runtime-link=shared threading=multi debug release 注意上面的命令行中,等号两端的变量不能留有空格,比如-toolset = msvc-8.0会报错。这样子,就将使用VC2005,以生成多线程版本的,同时生成调试版和发行版的动态链接库文件的形式构建所有需要构建的boost库,如果想生成所有版本的:包括单多线程,静态动态链接的,调试版发行版的全部都有的库,则可以用下面一句命令搞定: bjam --toolset=msvc-8.0 --build-type=complete

从计算着色器到四边形【翻译】

原文地址 // input texture Texture2D<float3> _sourceTexture; // a compute buffer that we can append to for output AppendStructuredBuffer<int2> _brightPoints; 在上面的代码段中,_sourceTexture是从外部传给GPU的纹理。和在fragment shader中访问纹理不一样的是,在片元着色器中通过采样器(sampler)获取纹理,纹理坐标是浮点数,而在compute shader中,“纹理”可以视为一个二维数组,可以通过整数索引值,直接访问这“二维数组”中的元素——纹素。 AppendStructedBuffer AppendStructuredBuffer 可视为是原始缓冲区的“升级版”,即结构化缓冲区。原始缓冲区(raw buffer)只是一个字节数组,而结构化缓冲区意味着可以为缓冲区中的每个元素定义一个结构。可以用来AppendStructuredBuffer.Append()方法将元素从缓冲区的末尾加入。重AppendStructuredBuffer.Append()是一个线程安全的操作。即使有数千个线程同时尝试向缓冲区添加某些内容,也不会产生冲突。 // tell Unity that the function "FindBrights" is a compute kernel #pragma kernel FindBrights // define thread groups for the FindBrights kernel [numthreads(32, 32, 1)] pragma kernel 指令 #pragma kernel FindBrights是Unity专用的代码。用来通知Unity函数FindBrights是计算内核(compute kernel),这意味着它可以用作计算着色器,而不仅仅是一个普通函数。 numthreads指令 numthreads指令的三个输入参数分别表示该着色器在工作组(Work Group)内的线程布局。具体来说,numthreads(x, y, z)指令中xyz三个参数分别定义了在X、Y和Z三个维度上每个工作组中线程的数量。这三个参数决定了工作组内线程的总数量,例如numthreads(8, 8, 1) 就定义了一个工作组包含 8 x 8 x 1 = 64 个线程。工作组的总线程数直接影响计算的并行性,在实际调用时,通过Dispatch()函数定义工作组的分布。如下代码:

在Unity3D中使用Visual Studio调试shader【翻译】

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 原文地址 本文主要介绍在U3D中调试shader代码的主要技术:false-color images:通过设置片元颜色中的某个分量,使得该值可视。然后根据resulting image中的颜色分量的亮度(intensity of that color component),你可以得到shader代码中的值的结论,这种技术的确是一种很原始的调试技术,但不幸的是,这在U3D中并不是不常见的。 1 顶点数据来自何方 在RGB cube一节中,你可以看到片元着色器如何通过顶点着色器输出的结构体中,获取到对应的数据。那么问现在的问题是:顶点着色器从何方拿到这些数据?在U3D环境下,答案是从绑定到game object中的Mesh Renderer组件中获取。Mesh Renderer组件将在每一帧中所有的发送网格顶点数据给OpenGL。这一步发送操作通常被称为“draw call”。必须注意的是,每一个的draw call都有一些性能耗费(performance overhead)。因而,一次性地给OpenGL发送一个大的网格数据,比分多次发送,每次发送一些较小的网格数据,要来得更高效些。这些网格数据通常由一系列的三角形组成,而每一个三角形则是以”三个顶点数据和一些其他属性数据“的方式被定义。这些属性数据将会通过”顶点输入参数(vertex input parameter)“的方式在顶点着色器中被启用。每一个顶点输入参数将会指定一系列的语义,如POSITION, NORMAL, TEXCOORD0, TEXCOORD1, TANGENT, COLOR等等。在U3D环境下的Cg语言的特定编程实现中。这些内建的顶点输入参数将会由一个特定的名字。 2 内建的顶点输入参数,以及如何使得它们可视 在U3D中的,内建的顶点输入参数不仅仅有特定的语义表示符号,还有特定的变量名字和类型,此外,他们还被包含在一个单独的结构体中,如下: struct vertexInput { float4 vertex:POSITION; // position (in object coordinates, i.e. local or model coordinates) float4 tangent:TANGENT; // vector orthogonal to the surface normal float3 normal:NORMAL; //surface normal vector (in object coordinates; usually normalized to unit //length float4 texcoord:TEXCOORD0; //0th set of texture coordinates (a.

Leap Motion的坐标系和变换操作(翻译)

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 原文地址 Coordinate Systems A fundamental task when using the Leap Motion controller in an application is mapping the coordinate values received from the controller to the appropriate application-defined coordinate system. 在一个应用里面使用Leap Motion控制器的一个基本的任务是:把从控制器处接收到的基于Leap Motion坐标系下的坐标值,转换到对应的应用内定义的坐标系下。 Leap Motion Coordinates The Leap Motion Controller provides coordinates in units of real world millimeters within the Leap Motion frame of reference. That is, if a finger tip’s position is given as (x, y, z) = [100, 100, -100], those numbers are millimeters – or, x = +10cm, y = 10cm, z = -10cm.

Unity3D PlayerPrefs的存储位置

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 平台 存储位置 macOS 存储在 【~/Library/Preferences】 目录下名字为 【unity.[company name].[product name].plist】 文件中,其中的 【company name】 和 【product names】 在 【Project Settings】 面板中设置。而且这个plist文件是为编辑器版本和单独可执行版本的程序共同使用。 Windows 存在注册表中的注册项中,该注册项的路径是 【HKEY_CURRENT_USER\Software[company name][product name]】。其中的 【company name】 和 【product names】 在 【Project Settings】 面板中设置。注意编辑器版本和单独可执行版本的注册表路径是不同的,例如 【company name】 是 “TomCompany” ,例如 【product name】 是 “TomGame” 的话,在编辑器中执行程序,其注册项路径为 【计算机\HKEY_CURRENT_USER\Software\Unity\UnityEditor\TomCompany\TomGame】 Linux PlayerPrefs存储在 【~/.config/unity3d/[CompanyName]/[ProductName]】 。其中的 【company name】 和 【product names】 在 【Project Settings】 面板中设置.。 Windows Store Apps PlayerPrefs存储在 【%userprofile%\AppData\Local\Packages[ProductPackageId]\LocalState\playerprefs.dat】 文件中 Windows Phone 8 PlayerPrefs存储在应用的 “local folder” 中,可查阅Directory.

Windows平台上无法启动Android ADB Server的解决方案

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 在Windows系统上使用adb时。经常会出现adb devices命令长时间无响应、adb start-server 失败、eclipse adt初始化时卡在dbms-init上等现象。造成这个问题的大部分原因,是在于adb server所默认使用的5037号端口被占用了。这种情况尤其在Windows系统装了类似于360手机助手等软件时经常出现。比如360助手在启动之后,会启动一个名字为360MobileLink.exe的进程。这个进程一般会占用这个默认端口号。 解决这个问题的最直接野蛮的方法,就是找出占用5037端口的进程,然后关闭它。我们可以使用命令行操作,如下: netstat -aon | findstr 127.0.0.1:5037 执行此命令后,便会打印出占用这个端口的进程的PID,根据这个PID值。我们再输入命令如下: tasklist|findstr "进程PID" 执行此命令后,便会打印出这个进程对应的可执行文件名,启动任务管理器关闭它即可。关闭了这个进程后,执行 adb kill-server adb start-server 便可重新启动adb server。所以在开发时,最好先打开elipse等软件,启动了adb之后,再启动360手机助手等软件,才不会发生这种占用端口的问题。 还有另一种方法就是自己配置adb server使用的端口号,只要在系统环境变量中定义 ANDROID_ADB_SERVER_PORT 的值即可。最好选择一个5位数的端口号(10000 ~ 65535),使用一个生僻的值。不易重复。Windows下只要在环境变量中增加一个ANDROID_ADB_SERVER_PORT值填你自己定义的端口。Linux下只要 export $ANDROID_ADB_SERVER_PORT = 自定义端口,即可。