@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
133 lines (102 loc) • 4.3 kB
JavaScript
import { vec3 } from "gl-matrix";
import { dataTypeFromTypedArray } from "../../../../../core/binary/type/dataTypeFromTypedArray.js";
import { v3_array_matrix4_rotate } from "../../../../../core/geom/vec3/v3_array_matrix4_rotate.js";
import { v3_distance_sqr } from "../../../../../core/geom/vec3/v3_distance_sqr.js";
import { decode_attribute_value } from "../../../geometry/decode_attribute_value.js";
import { geometry_construct_triangle_normal } from "../../../geometry/geometry_construct_triangle_normal.js";
import { sample_triangle_attribute } from "../geometry/sample_triangle_attribute.js";
import { v3_orthonormal_matrix_from_normal } from "../sampling/v3_orthonormal_matrix_from_normal.js";
const texture_uv = [0, 0];
const color = new Float64Array(3);
const normal = new Float32Array(3);
const scratch_m3 = new Float32Array(9);
/**
*
* @param {number[]} color
* @param {BufferAttribute} color_attribute
* @param {number} index_0
* @param {number} index_1
* @param {number} index_2
* @param {number} u
* @param {number} v
*/
function sample_color_attribute(
color,
color_attribute,
index_0, index_1, index_2,
u, v
) {
const color_array = color_attribute.array;
sample_triangle_attribute(color, 0, index_0, index_1, index_2, color_array, color_attribute.itemSize, u, v);
const type = dataTypeFromTypedArray(color_array);
for (let i = 0; i < 3; i++) {
color[i] = decode_attribute_value(
color[i], type, color_attribute.normalized
);
}
}
/**
*
* @param {number[]} out
* @param {PathTracedMesh} mesh
* @param {number} primitive_id
* @param {number} u
* @param {number} v
*/
export function sample_material(
out,
mesh,
primitive_id,
u, v
) {
const material = mesh.material;
const geometry = mesh.geometry;
const index_attribute = geometry.getIndex();
const index_array = index_attribute.array;
// sample surface normal
const index_offset = primitive_id * 3;
const index_0 = index_array[index_offset];
const index_1 = index_array[index_offset + 1];
const index_2 = index_array[index_offset + 2];
const normal_attribute = geometry.getAttribute('normal');
if (normal_attribute !== undefined) {
// vertex normals are present, use those
const normal_array = normal_attribute.array;
sample_triangle_attribute(out, 3, index_0, index_1, index_2, normal_array, 3, u, v);
} else {
const position_attribute = geometry.getAttribute('position');
// copy hit normal
geometry_construct_triangle_normal(out, 3, index_0, index_1, index_2, position_attribute.array);
}
// apply transform
v3_array_matrix4_rotate(out, 3, out, 3, mesh.transform);
material.normal.sample(normal, texture_uv[0], texture_uv[1]);
if (v3_distance_sqr(normal[0], normal[1], normal[2], 0.5, 0.5, 1) > 0.01) {
//
normal[0] = normal[0] * 2 - 1;
normal[1] = normal[1] * 2 - 1;
normal[2] = normal[2] * 2 - 1;
vec3.normalize(normal, normal);
// needs transform
v3_orthonormal_matrix_from_normal(scratch_m3, 0, out[3], out[4], out[5]);
out[3] = scratch_m3[0] * normal[0] + scratch_m3[3] * normal[1] + scratch_m3[6] * normal[2];
out[4] = scratch_m3[1] * normal[0] + scratch_m3[4] * normal[1] + scratch_m3[7] * normal[2];
out[5] = scratch_m3[2] * normal[0] + scratch_m3[5] * normal[1] + scratch_m3[8] * normal[2];
}
const uv_attribute = geometry.getAttribute('uv');
if (uv_attribute !== undefined) {
const uv_array = uv_attribute.array;
sample_triangle_attribute(texture_uv, 0, index_0, index_1, index_2, uv_array, 2, u, v);
} else {
// default texture uv
texture_uv[0] = 0;
texture_uv[1] = 0;
}
const color_attribute = geometry.getAttribute('color');
if (color_attribute !== undefined) {
sample_color_attribute(color, color_attribute, index_0, index_1, index_2, u, v);
vec3.multiply(out, out, color);
}
material.diffuse.sample(color, texture_uv[0], texture_uv[1]);
vec3.multiply(out, out, color);
}