Javascript 在webgl场景中使用法线应用平行光时出现的问题

Javascript 在webgl场景中使用法线应用平行光时出现的问题,javascript,graphics,normalization,shader,webgl,Javascript,Graphics,Normalization,Shader,Webgl,好, 因此,我一直在网络上寻找使用法线和平行光正确渲染的方法,这些方法最初可以在learningwebgl.com教程中找到。在learningwebgl教程中,法线都设置在一个数组中。在我的程序中,我需要能够加载wavefont OBJ文件,然后生成法线。我想知道这是否可能是我的正常生成代码,或者可能是我的着色器有问题。代码有点混乱,因为所有顶点/法线/索引数据都在单个数组中,但下面是我的正常生成代码: for(var i=0;i<d["vertices"].length;i++

好,

因此,我一直在网络上寻找使用法线和平行光正确渲染的方法,这些方法最初可以在learningwebgl.com教程中找到。在learningwebgl教程中,法线都设置在一个数组中。在我的程序中,我需要能够加载wavefont OBJ文件,然后生成法线。我想知道这是否可能是我的正常生成代码,或者可能是我的着色器有问题。代码有点混乱,因为所有顶点/法线/索引数据都在单个数组中,但下面是我的正常生成代码:

    for(var i=0;i<d["vertices"].length;i++)d["normals"][i] = 0;     

    for(var i=0;i<d["indices"].length/3;i++){

        var a = [d["vertices"][d["indices"][(i*3)]], d["vertices"][d["indices"][(i*3)]+1], d["vertices"][d["indices"][(i*3)]+2]];
        var b = [d["vertices"][d["indices"][(i*3)+1]], d["vertices"][d["indices"][(i*3)+1]+1], d["vertices"][d["indices"][(i*3)+1]+2]];
        var c = [d["vertices"][d["indices"][(i*3)+2]], d["vertices"][d["indices"][(i*3)+2]+1], d["vertices"][d["indices"][(i*3)+2]+2]];

        var e = vec3.cross(vec3.subtract(b, a), vec3.subtract(c, a));

        d["normals"][d["indices"][(i*3)]] += -e[0];
        d["normals"][d["indices"][(i*3)]+1] += -e[1];
        d["normals"][d["indices"][(i*3)]+2] += -e[2];

        d["normals"][d["indices"][(i*3)+1]] += -e[0];
        d["normals"][d["indices"][(i*3)+1]+1] += -e[1];
        d["normals"][d["indices"][(i*3)+1]+2] += -e[2];

        d["normals"][d["indices"][(i*3)+2]] += -e[0];
        d["normals"][d["indices"][(i*3)+2]+1] += -e[1];
        d["normals"][d["indices"][(i*3)+2]+2] += -e[2];
    }

    for(var i=0;i<d["normals"].length/3;i++){
        var old = vec3.normalize([d["normals"][(i*3)],d["normals"][(i*3)+1],d["normals"][(i*3)+2]]);
        d["normals"][(i*3)] = old[0];
        d["normals"][(i*3)+1] = old[1];
        d["normals"][(i*3)+2] = old[2];
    }
我尝试过许多普通算法,但都没有用。我还发现,如果我不在最后规范化法线,颜色/阴影实际上会改变,这显然是不正确的阴影

要了解底部循环的当前外观示例,请遵循此链接,从下拉列表中选择teddy,然后单击“加载”,然后单击“重新生成法线”,然后可以通过拖动鼠标围绕teddy旋转:

要查看着色器,请参见以下内容:

我已经在这个问题上纠缠了好几个小时,我开始怀疑它是否与着色器相关,但是我对graphicaly编程还是新手,非常感谢您的帮助:

*使用的矩阵库是glMatrix


干杯,Josh

我无法在model_engine.js第107行加载演示分配大小溢出,但我将您的着色器代码扔到了我的引擎中,它运行良好

然后我仔细查看了你的JS代码,然后。。。嗯,我认为这几乎是完全错误的。看起来你要做的第一件事就是取每个面的法线,这是一个好的开始,但我不明白你为什么要否定e的值。你也应该在这一点上规范化,因为现在它只是一个任意长度的向量。但我不知道这是否真的重要

接下来要做的是取给定顶点的所有E的和的法线。不完全正确:您需要规范化所有E的平均值,而不是总和

最后,我想到的是。它在我自己的引擎中工作得很好,而且它的启动速度似乎比原始版本快得多。免责声明:可能仍然需要进行一些优化。我写它是为了清晰,不是为了速度

var i, j, normals = {};

// calculate face normals. Note that each vertex will have a number of faces
// adjacent to it, so we accumulate their normals into an array. We'll take
// the average of them all when done.
var tmp1 = vec3.create(), tmp2 = vec3.create();
var a, b, c;

function pushNormal(index, normal) {
  normals[index] = normals[index] || [];
  normals[index].push(normal);
}

for (i = 0; i < d["indices"].length; i += 3) {
  // get points a, b, c
  var aIndex = d["indices"][i], bIndex = d["indices"][i+1], cIndex = d["indices"][i+2];
  var aOffsetX = aIndex * 3, aOffsetY = aIndex * 3 + 1, aOffsetZ = aIndex * 3 + 2;
  var bOffsetX = bIndex * 3, bOffsetY = bIndex * 3 + 1, bOffsetZ = bIndex * 3 + 2;
  var cOffsetX = cIndex * 3, cOffsetY = cIndex * 3 + 1, cOffsetZ = cIndex * 3 + 2;

  a = [d["vertices"][aOffsetX], d["vertices"][aOffsetY], d["vertices"][aOffsetZ]];
  b = [d["vertices"][bOffsetX], d["vertices"][bOffsetY], d["vertices"][bOffsetZ]];
  c = [d["vertices"][cOffsetX], d["vertices"][cOffsetY], d["vertices"][cOffsetZ]];

  // calculate face normal
  vec3.subtract(b, a, tmp1);
  vec3.subtract(c, a, tmp2);
  var e = vec3.normalize(vec3.cross(tmp1, tmp2, vec3.create()));

  // accumulate face normal for each of a, b, c
  pushNormal(a, vec3.create(e));
  pushNormal(b, vec3.create(e));
  pushNormal(c, vec3.create(e));
}

// now calculate normalized averages for each face normal, and store the result
for (i = 0; i < d["vertices"].length; i += 3) {
  a = [d["vertices"][i], d["vertices"][i+1], d["vertices"][i+2]];
  if (normals[a]) {
    var avg = vec3.create();
    for (j = 0; j < normals[a].length; j++) {
      vec3.add(normals[a][j], avg, avg);
    }
    vec3.scale(avg, 1/normals[a].length);
    vec3.normalize(avg);

    d["normals"][i] = avg[0];
    d["normals"][i+1] = avg[1];
    d["normals"][i+2] = avg[2];
  }
}

// sanity check
if (d["normals"].length != d["vertices"].length)
  alert("ERROR "+d["normals"].length+" != "+d["vertices"].length);
希望这有帮助

var i, j, normals = {};

// calculate face normals. Note that each vertex will have a number of faces
// adjacent to it, so we accumulate their normals into an array. We'll take
// the average of them all when done.
var tmp1 = vec3.create(), tmp2 = vec3.create();
var a, b, c;

function pushNormal(index, normal) {
  normals[index] = normals[index] || [];
  normals[index].push(normal);
}

for (i = 0; i < d["indices"].length; i += 3) {
  // get points a, b, c
  var aIndex = d["indices"][i], bIndex = d["indices"][i+1], cIndex = d["indices"][i+2];
  var aOffsetX = aIndex * 3, aOffsetY = aIndex * 3 + 1, aOffsetZ = aIndex * 3 + 2;
  var bOffsetX = bIndex * 3, bOffsetY = bIndex * 3 + 1, bOffsetZ = bIndex * 3 + 2;
  var cOffsetX = cIndex * 3, cOffsetY = cIndex * 3 + 1, cOffsetZ = cIndex * 3 + 2;

  a = [d["vertices"][aOffsetX], d["vertices"][aOffsetY], d["vertices"][aOffsetZ]];
  b = [d["vertices"][bOffsetX], d["vertices"][bOffsetY], d["vertices"][bOffsetZ]];
  c = [d["vertices"][cOffsetX], d["vertices"][cOffsetY], d["vertices"][cOffsetZ]];

  // calculate face normal
  vec3.subtract(b, a, tmp1);
  vec3.subtract(c, a, tmp2);
  var e = vec3.normalize(vec3.cross(tmp1, tmp2, vec3.create()));

  // accumulate face normal for each of a, b, c
  pushNormal(a, vec3.create(e));
  pushNormal(b, vec3.create(e));
  pushNormal(c, vec3.create(e));
}

// now calculate normalized averages for each face normal, and store the result
for (i = 0; i < d["vertices"].length; i += 3) {
  a = [d["vertices"][i], d["vertices"][i+1], d["vertices"][i+2]];
  if (normals[a]) {
    var avg = vec3.create();
    for (j = 0; j < normals[a].length; j++) {
      vec3.add(normals[a][j], avg, avg);
    }
    vec3.scale(avg, 1/normals[a].length);
    vec3.normalize(avg);

    d["normals"][i] = avg[0];
    d["normals"][i+1] = avg[1];
    d["normals"][i+2] = avg[2];
  }
}

// sanity check
if (d["normals"].length != d["vertices"].length)
  alert("ERROR "+d["normals"].length+" != "+d["vertices"].length);