CG

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.

软渲染示例程序Tiny3D的实现简介

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 绘制图形的代码 Tiny3D核心的图形绘制代码调用栈如下图所示 Device::DrawBox函数 Tiny3D的核心绘制代码的入口函数Device::DrawBox函数 // theta mesh的旋转角度 // box_vertices mesh的原始模型顶点数据 void Device::DrawBox(float theta, const T3DVertex* box_vertices) Device::DrawBox函数的实现如下代码所示: void Device::DrawBox(float theta, const T3DVertex* box_vertices) { T3DMatrix4X4 m; T3DMatrixMakeRotation(&m, -1.0f, -0.5f, 1.0f, theta); transform_.SetWorldMatrix(m); transform_.Update(); DrawPlane(&box_vertices[0], &box_vertices[1], &box_vertices[2], &box_vertices[3]); DrawPlane(&box_vertices[4], &box_vertices[5], &box_vertices[6], &box_vertices[7]); DrawPlane(&box_vertices[0], &box_vertices[4], &box_vertices[5], &box_vertices[1]); DrawPlane(&box_vertices[1], &box_vertices[5], &box_vertices[6], &box_vertices[2]); DrawPlane(&box_vertices[2], &box_vertices[6], &box_vertices[7], &box_vertices[3]); DrawPlane(&box_vertices[3], &box_vertices[7], &box_vertices[4], &box_vertices[0]); } 步骤就是如下的几步: 根据传递进来的mesh的旋转角度theta,调用T3DMatrixMakeRotation函数构建world matrix,然后更新到Transform类中去 调用Transform::Update函数,更新world-view-projection matrix,这WVP matrix将在后面的用来变换顶点。 把一个六面体BOX拆分成6个矩形面,调用DrawPlane函数进行绘制。 Device::DrawPlane函数 Device::DrawPlane函数的实现如下代码所示: void Device::DrawPlane(const T3DVertex* p1, const T3DVertex* p2, const T3DVertex* p3, const T3DVertex* p4) { T3DVertex _p1 = *p1, _p2 = *p2, _p3 = *p3, _p4 = *p4; _p1.