【问题标题】:How calculate light level for opening?如何计算开放的光照水平?
【发布时间】:2016-03-11 02:29:07
【问题描述】:

我构建了锥体的 3D 模型。目前我做光。


无光
有光

黄点 - 太阳
粉红点 - 刻面中心
白点 - 法线末端

var light = new BABYLON.Vector3(120, 100, 0);
...
var currentFace = mesh.Facets[indexFaces];
var pixelA = this.project(currentFace.A, transformMatrix);
var pixelB = this.project(currentFace.B, transformMatrix);
var pixelC = this.project(currentFace.C, transformMatrix);
var normal1 = BABYLON.Vector3.Cross(pixelA, pixelB);
var normal2 = BABYLON.Vector3.Cross(pixelB, pixelC);
var normal3 = BABYLON.Vector3.Cross(pixelC, pixelA);
var center = pixelA.add(pixelB).add(pixelC).scale(1 / 3);
var normal = normal1.add(normal2).add(normal3).scale(1 / 3);
var end = center.add(normal.scale(5));
...
var lightDirection = light.subtract(center);
normal.normalize();
lightDirection.normalize();
var ndotl Math.max(0, BABYLON.Vector3.Dot(normal, lightDirection));

我做错了什么?
感谢您的提前!
附言作为基地,我拿了这个tutorial

UPDATE-1

我重写了我的渲染方法,现在效果比以前好得多:

    Device.prototype.render = function (cfg, mesh) {
        var self = this,
            normals = [], normal, center, end, color, ndotl, light = cfg.light.clone(),
            pixelA, pixelB, pixelC, pixelWorldA, pixelWorldB, pixelWorldC, normalA, normalB, normalC,
            viewMatrix, projectionMatrix, worldMatrix, worldViewTransformation, transformMatrix;
        viewMatrix = BABYLON.Matrix.LookAtLH(cfg.camera.position, cfg.camera.target, BABYLON.Vector3.Up());
        projectionMatrix = BABYLON.Matrix.PerspectiveFovLH(
            cfg.perspective.fov / 180,
            cfg.perspective.aspect,
            cfg.perspective.znear,
            cfg.perspective.zfar,
            cfg.perspective.distance);
        worldMatrix = BABYLON.Matrix.RotationYawPitchRoll(
            cfg.rotation.y / 180,
            cfg.rotation.x / 180,
            cfg.rotation.z / 180).multiply(BABYLON.Matrix.Translation(
                cfg.translation.x,
                cfg.translation.y,
                cfg.translation.z));
        worldViewTransformation = worldMatrix.multiply(viewMatrix);
        transformMatrix = worldViewTransformation.multiply(projectionMatrix);
        mesh.facets.forEach(function (facet) {
            pixelA = self.project(facet.a, transformMatrix);
            pixelB = self.project(facet.b, transformMatrix);
            pixelC = self.project(facet.c, transformMatrix);
            pixelWorldA = BABYLON.Vector3.TransformCoordinates(facet.a, worldViewTransformation);
            pixelWorldB = BABYLON.Vector3.TransformCoordinates(facet.b, worldViewTransformation);
            pixelWorldC = BABYLON.Vector3.TransformCoordinates(facet.c, worldViewTransformation);
            normalA = BABYLON.Vector3.Cross(pixelWorldA, pixelWorldB);
            normalB = BABYLON.Vector3.Cross(pixelWorldB, pixelWorldC);
            normalC = BABYLON.Vector3.Cross(pixelWorldC, pixelWorldA);
            center = pixelA.add(pixelB).add(pixelC).scale(1 / 3);
            normal = normalA.add(normalB).add(normalC).scale(1 / 3);
            end = center.add(normal.scale(20000));
            normals.push({start: center, end: end});
            ndotl = self.computeNDotL(center, normal, light);
            color = new BABYLON.Color4(ndotl * facet.color.r, ndotl * facet.color.g, ndotl * facet.color.b, ndotl * facet.color.a);
            self.drawTriangle(pixelA, pixelB, pixelC, color);
        });
        self.present();
        self.workingContext.fillStyle = "yellow";
        self.workingContext.fillRect(light.x - 10, light.y - 10, 20, 20);
        self.workingContext.strokeStyle = "#ffffff";
        normals.forEach(function (p) {
            var p1 = p.start;
            var p2 = p.end;
            self.workingContext.beginPath();
            self.workingContext.moveTo(p1.x, p1.y);
            self.workingContext.lineTo(p2.x, p2.y);
            self.workingContext.stroke();
            self.workingContext.fillStyle = "#ffffff";
            self.workingContext.fillRect(p1.x - 2, p1.y - 2, 5, 5);
            self.workingContext.fillStyle = "#ff00ff";
            self.workingContext.fillRect(p2.x - 2, p2.y - 2, 5, 5);
        });
    };

在这段代码中,我添加了世界观矩阵。 我目前的结果:

你说,要隐藏锥形内部的红色区域,我可以使用 z-buffer。 但是...如何?

【问题讨论】:

  • 我敢打赌,你的坐标系是正常的,光线是相反的,所以试试var ndotl Math.max(0, - BABYLON.Vector3.Dot(normal, lightDirection)); ...只是添加了减号。你还在渲染中使用ndot 照明强度吗? (您应该将面部颜色乘以它并渲染面部)

标签: javascript graphics 3d


【解决方案1】:

@Spektre,

你还在渲染中使用 ndot 照明强度吗?

是的,我就是这样做的:

var c = new BABYLON.Color4(ndotl * currentFace.Color.r, ndotl * currentFace.Color.g, ndotl * currentFace.Color.b, 1.0);
this.drawTriangle(pixelA, pixelB, pixelC, c);

刚刚添加了减号。

不受影响

如果我要更改我的代码,那么灯会亮,但它不能正常工作

for (var indexFaces = 0; indexFaces < mesh.Facets.length; indexFaces++) {
    var currentFace = mesh.Facets[indexFaces];
    var pixelA = this.project(currentFace.A, transformMatrix);
    var pixelB = this.project(currentFace.B, transformMatrix);
    var pixelC = this.project(currentFace.C, transformMatrix);
    var normal1 = BABYLON.Vector3.Cross(currentFace.A, currentFace.B);
    var normal2 = BABYLON.Vector3.Cross(currentFace.B, currentFace.C);
    var normal3 = BABYLON.Vector3.Cross(currentFace.C, currentFace.A);
    normal1 = BABYLON.Vector3.TransformCoordinates(normal1, worldMatrix);
    normal2 = BABYLON.Vector3.TransformCoordinates(normal2, worldMatrix);
    normal3 = BABYLON.Vector3.TransformCoordinates(normal3, worldMatrix);
    var center = pixelA.add(pixelB).add(pixelC).scale(1 / 3);
    var normal = normal1.add(normal2).add(normal3).scale(1 / 3);
    var end = center.add(normal.scale(10000));
    centers.push({p1: center, p2: end});
    var ndotl = this.computeNDotL(center, normal, cfg.light);
    var c = new BABYLON.Color4(ndotl * currentFace.Color.r, ndotl * currentFace.Color.g, ndotl * currentFace.Color.b, 1.0);
    //console.log("center:"+center+", angle: " + (ndotl * 180) + ", cos: " + ndotl + ", type: " + currentFace.Type + ", color:" + c);
    this.drawTriangle(pixelA, pixelB, pixelC, c);
}

要计算法线,我必须使用原始模型的点(在应用转换之前)或之后(在我的情况下,这个点:pixelA,pixelB,pixelC)?

【讨论】:

  • 您应该将此作为编辑而不是作为答案发布到您的问题中...... @notification 仅在 cmets 中有效。这张图片对我来说看起来不错,可能你想添加一些环境光....c=face_color*(c_ambient+c_diffuse*ndotl) 环境光约为 25%,漫反射为 75%。或使用abs(ndotl) 来制作双面多边形(但通常不与实体一起使用
  • 你也应该只绘制视图中的法线(基于多边形缠绕或 Z-Buffer)
  • 您可以在需要时计算法线,但点积必须在同一坐标系中的向量上完成......所以要么使用局部坐标系,但您需要将光位置转换为它或使用全局坐标系,但是你需要使用 A、B、C 变换到它...如果你将所有变换堆叠到一个,那么你在变换后得到屏幕空间坐标并且还需要变换灯光位置...
  • 你能解释一下,我如何使用 z-buffer 来隐藏锥体内部的刻面?
  • Z-buffer zed 是另一个屏幕(二维数组),它只存储像素的 Z 坐标而不是像素的颜色。它具有与渲染屏幕相同的分辨率 (scr)。在渲染之前,你用相机中尽可能远的 Z 值填充它(对于 32bit int 0x7FFFFFFF)。然后将您的setpixel(x,y,color)scr[y][x]=color 更改为void setpixel(int x,int y,int z,DWORD color) { if (zed[y][x]&gt;=z) { zed[y][x]=z; scr[y][x]=color; }} 之类的东西,这样它就只渲染来自相机的可见像素...
猜你喜欢
  • 2015-01-12
  • 2023-03-17
  • 2018-10-13
  • 1970-01-01
  • 2012-05-12
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
  • 2015-02-05
相关资源
最近更新 更多