Я не могу загрузить вашу демонстрацию (переполнение размера выделения в строке model_engine.js 107), но я бросил ваш код шейдера в мой движок ( бесстыдный плагин: проверьте Jax, это действительно круто! ) и все работало нормально.
Затем я внимательно посмотрел на ваш код JS и ... ну, я считаю, что это в значительной степени совершенно неправильно. Похоже, первое, что вы делаете, это берете нормаль каждого лица - хорошее начало, но я не понимаю, почему вы отрицаете значение e
. Вы также должны нормализовать e
в этой точке, потому что сейчас это просто вектор произвольной длины. Не знаю, действительно ли это имеет значение.
Следующее, что вы делаете, берете нормаль от суммы всех e
s для данной вершины. Не совсем верно: вам нужно нормализовать среднее всех 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);
Надеюсь, это поможет!