UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

133 lines (102 loc) 4.3 kB
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); }