zoukankan      html  css  js  c++  java
  • 万花筒模拟

    背景介绍

    还不知道什么是万花筒的小朋友请点击这里:

     最常见的万花筒,侧边是由三面镜子构成的,镜子不断反射底部的图像,产生千变万化的组合。它产生的图像比如:

     (图1)(图2)

    为了更清晰的解释,我们用下面的图为例:

    (图3)

    以上图ABC为例 ,真实的图像是中间最亮的三角形部分,其余的镜像都是由镜子反射造成的。

    我们的目标就是要用计算机模拟万花筒生成的图像。

    目标详解

    输入:

    底图,以上面ABC为例,就是中间最亮的三角形部分;

    输出:

    以底图为基础,正确的绘制出反射图像。不仅要考虑最简单的平铺形式(ABC这个例子就是平铺);还要考虑万花筒的镜子可以调整,比如调整后可以生成图2所示的结果。

    具体目标:

    -正确的处理图像镜像;

    -模拟镜子的非理想表面,比如散射和反照率。

    目标分析

    •  处理图像镜像

    有两个备选方案:

    方法一,中心图像是原始图像,其它部分都是原始图像的镜像,很自然想到算出正确的镜像平铺开即可。基本原理如下图所示。

    但是为了模拟更一般的情况(比如图2),镜像是在三维空间而不是二维空间中计算的。另外,要考虑到镜像之间交叉或者重叠情况。

    除了以上这些问题,这个方法最重要的潜在的问题是:由于并非物理模拟,不容易扩展;比如镜子的材质或形状改变,很可能会导致这种方法的失效。

    当然,这个方法的优点也很明显,就是效率,如果用GPU实现,几乎没有什么计算,除了简单的纹理采样计算。

    考虑到我们的主要是用于实验目的,效率的要求不是特别迫切,我们尝试寻找更接近物理的模拟方法。

    方法二,光线跟踪。不了解光线跟踪但感兴趣的同学请wiki之。

    适合用光线跟踪的原因如下:接近物理真实情况;在万花筒有限的空间内,光线跟踪计算也比较简单。二维简化图示意如下:

     

    • 模拟镜子的非理想表面

    现实世界的镜子不是完美的,模拟的时候可以把这些“缺陷”也考虑进去。我想到两点:

    一个是反照率(albedo),我们需要在每一次反射的时候,乘以一个小于1的系数来实现。它产生的效果就是中间图像最亮,越往外图像越暗。

    另外一个是漫反射,非理想镜子表面也存在漫反射。经过多次反射后,产生的效果是图像的模糊;反射次数越多,图像模糊度越大。ray trace的时候产生漫反射的光线可以解决这个问题,但是会使计算量按几何级数增加,这个计算量目前是无法负担的。最简单的模拟办法是通过mipmap来模拟,反射次数越多的地方采用尺寸越小的mipmap slice,当然这个方法并不精确,和实际效果是有偏差的。

    • 在现实基础上的扩展

    除了模拟现实,我们可以在我们创造的虚拟世界中加入现实中不存在的元素,或做各种奇怪的实验。

    比如,镜子的面数可以改变,镜子之间的夹角可以随意改变。

    比如,镜子可以有倾斜度(即和底面的夹角并非直角),图2就是一个实例。

    比如,底面(即原始图平面)本身也可以倾斜。

    比如,镜子反射光线的时候,可以使用抖动技术;这样反射次数多的地方,会产生溶解的效果。

    确定方案

    使用D3D在Pixel Shader中做ray trace的核心计算,充分利用GPU的并行计算能力;

    在单独窗口中设置参数,不占用主界面的显示空间。

    此版本结果展示

    截图

    下载地址

    https://files.cnblogs.com/mchz/Kaleidescope_v1.0.0.1.rar

    运行环境要求

    WinXP SP2 or Higher
    DirectX11 Runtime & DirectX10 Supported Video Card
    VS2012 Runtime(https://files.cnblogs.com/mchz/vcredist_x86.rar)

    功能详述

    ----------
    |V1.0.0.1|
    ----------
    第一个版本。本应用的目的是模拟万花筒。核心功能通过D3D在GPU上实现。
    此版本实现的功能有:
    支持三面镜子,且三面镜子组成一个柱体或台体,剖面是正三角形(这也是现实中绝大多数万花筒的实现方式)。
    可调节的参数是:
    -设置底图: 底图指的是万花筒底部的实际物体(比如多彩碎屑),我们用图片文件模拟,支持拖拽图片到窗口;
    -支持底图缩放;
    -支持底图平移;
    -万花筒长度调节: 长度越长,底面离眼睛越远,镜子越长;
    -万花筒旋转速度调节;
    -可视圆半径: 指的是圆形Mask的半径。半径越小,在GPU上执行速度越快;
    -可调节镜子倾斜度: 这样三面镜子可组成台体(顶部和底部剖面大小不同)而不是一般的柱体。

  • 相关阅读:
    Redis详解----- 缓存穿透、缓存击穿、缓存雪崩
    mysql存储时间
    MAT入门到精通
    meven依赖思考记录
    线程池原理
    vscode + wsl2
    java架构师学习路线-高级
    java架构师学习路线-初级
    (二)垃圾回收
    (一)内存区域
  • 原文地址:https://www.cnblogs.com/mchz/p/3356999.html
Copyright © 2011-2022 走看看