使用 css 的 clip-path 渲染 3d 模型

2015-03-28 12:56:14 +08:00
 leeluolee

做了个比较好玩,但是暂时没多大意义的东西 clip3d

Demo on codepen

懂的人应该看得出 ,这个其实没有任何的css3的transform 3d来做到的, 是的完全是通过clip-path创造的三角形拼起来的。

与transform区别最大的么, 就是流程和常规3d渲染一致, 理论上可以渲染任何形状的物体(我没测试过性能), 也可以做简单的lighting 和 z-sorting.

当然这只是玩具了, 真实的3d rendering 当然不是这么回事, 光无法使用材质就基本判了死刑。

DEMO的代码如下

var Render = clip3d.Render,
  Light = clip3d.Light,
  Camera = clip3d.Camera,
  vec3 = clip3d.vec3,
  mat4 = clip3d.mat4,
  _ = clip3d.util,
  color = clip3d.color;

var render = new Render({
  parent: document.getElementById("app"),
  camera: new Camera({
    eye: [4,4, -10]
  }),
  // simple point-lighting
  light: new Light({
    position: [ 0, 0, -1 ],
    color: [255, 255, 255,1]
  }),
  // http://learningwebgl.com/blog/?p=370 
  // entity form learning webgl
  entities: [
    {
      vertices: [ 
        0,  1,  0,
        -1, -1, 1,
        1, -1,  1,

        0,  1,  0,
        1, -1,  1,
        1, -1, -1,

        0,  1,  0,
        1, -1, -1,
        -1, -1, -1,

        0,  1,  0,
        -1, -1, -1,
        -1, -1,  1,

        // warning the squence
        1, -1,  1,
        -1, -1, 1,
        -1, -1, -1,

        1, -1, -1,
        1, -1,  1,
        -1, -1, -1,

      ],
      colors: [
      ]
    },
    {
      vertices: [ 
  // Front face
      -1.0, -1.0,  1.0,
       1.0, -1.0,  1.0,
       1.0,  1.0,  1.0,
      -1.0,  1.0,  1.0,

      // Back face
      -1.0, -1.0, -1.0,
      -1.0,  1.0, -1.0,
       1.0,  1.0, -1.0,
       1.0, -1.0, -1.0,

      // Top face
      -1.0,  1.0, -1.0,
      -1.0,  1.0,  1.0,
       1.0,  1.0,  1.0,
       1.0,  1.0, -1.0,

      // Bottom face
      -1.0, -1.0, -1.0,
       1.0, -1.0, -1.0,
       1.0, -1.0,  1.0,
      -1.0, -1.0,  1.0,

      // Right face
       1.0, -1.0, -1.0,
       1.0,  1.0, -1.0,
       1.0,  1.0,  1.0,
       1.0, -1.0,  1.0,

      // Left face
      -1.0, -1.0, -1.0,
      -1.0, -1.0,  1.0,
      -1.0,  1.0,  1.0,
      -1.0,  1.0, -1.0
      ],
      indices : [
        0, 1, 2,      0, 2, 3,    // Front face
        4, 5, 6,      4, 6, 7,    // Back face
        8, 9, 10,     8, 10, 11,  // Top face
        12, 13, 14,   12, 14, 15, // Bottom face
        16, 17, 18,   16, 18, 19, // Right face
        20, 21, 22,   20, 22, 23  // Left face
      ],
      itemSize: 3,
      // for simplify. one face only have one color
      colors: [
        [255, 0, 0, 1],
        [255, 0, 0, 1],
        [255, 255, 0, 1],
        [255, 255, 0, 1],
        [0, 255, 0, 1],
        [0, 255, 0, 1],
        [255, 120 , 255, 1],
        [255, 120 , 255, 1],
        [120, 255, 0, 1],
        [120, 255, 0, 1],
        [0, 255, 120, 1],
        [0, 255, 120, 1]
      ],
      matrix: mat4.createRotate([0,0,1], 30)
    }
  ]
})
2398 次点击
所在节点    前端开发
2 条回复
14
2015-03-28 13:03:30 +08:00
Hi,这种方式怎么解决连接处的缝隙问题(如下图),以前拼接全景图的时候遇到过,试过一种方法,加1px的透明边框并不理想。
leeluolee
2015-03-28 15:08:38 +08:00
@14 可以解决, 将面向外扩展一点点就可以. 这个东西没写那么细致 所以没处理

不知道你是否知道以前的pre3d.里面有个简单的解决方案

```js
function elimGap(arr){
for(var i=0,l=arr.length;i<l;i++){
var end=(i+1)%l,dx=arr[end].x-arr[i].x,dy=arr[end].y-arr[i].y;
var ds=Math.sqrt(Math.pow(dx,2)+Math.pow(dy,2))*3;
arr[end].x+=(dx)/ds;
arr[end].y+=(dy)/ds;
arr[i].x-=(dx)/ds;
arr[i].y-=(dy)/ds;
}
}
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/179913

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX