UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

107 lines (96 loc) 3.11 kB
import TempNode from '../core/TempNode.js'; import { uv } from '../accessors/UV.js'; import { normalView } from '../accessors/Normal.js'; import { positionView } from '../accessors/Position.js'; import { faceDirection } from './FrontFacingNode.js'; import { Fn, nodeProxy, float, vec2 } from '../tsl/TSLBase.js'; // Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen // https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf const dHdxy_fwd = Fn(({ textureNode, bumpScale }) => { // It's used to preserve the same TextureNode instance const sampleTexture = callback => textureNode.cache().context({ getUV: texNode => callback(texNode.uvNode || uv()), forceUVContext: true }); const Hll = float(sampleTexture(uvNode => uvNode)); return vec2(float(sampleTexture(uvNode => uvNode.add(uvNode.dFdx()))).sub(Hll), float(sampleTexture(uvNode => uvNode.add(uvNode.dFdy()))).sub(Hll)).mul(bumpScale); }); // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) const perturbNormalArb = Fn(inputs => { const { surf_pos, surf_norm, dHdxy } = inputs; // normalize is done to ensure that the bump map looks the same regardless of the texture's scale const vSigmaX = surf_pos.dFdx().normalize(); const vSigmaY = surf_pos.dFdy().normalize(); const vN = surf_norm; // normalized const R1 = vSigmaY.cross(vN); const R2 = vN.cross(vSigmaX); const fDet = vSigmaX.dot(R1).mul(faceDirection); const vGrad = fDet.sign().mul(dHdxy.x.mul(R1).add(dHdxy.y.mul(R2))); return fDet.abs().mul(surf_norm).sub(vGrad).normalize(); }); /** * This class can be used for applying bump maps to materials. * * ```js * material.normalNode = bumpMap( texture( bumpTex ) ); * ``` * * @augments TempNode */ class BumpMapNode extends TempNode { static get type() { return 'BumpMapNode'; } /** * Constructs a new bump map node. * * @param {Node<float>} textureNode - Represents the bump map data. * @param {?Node<float>} [scaleNode=null] - Controls the intensity of the bump effect. */ constructor(textureNode, scaleNode = null) { super('vec3'); /** * Represents the bump map data. * * @type {Node<float>} */ this.textureNode = textureNode; /** * Controls the intensity of the bump effect. * * @type {?Node<float>} * @default null */ this.scaleNode = scaleNode; } setup() { const bumpScale = this.scaleNode !== null ? this.scaleNode : 1; const dHdxy = dHdxy_fwd({ textureNode: this.textureNode, bumpScale }); return perturbNormalArb({ surf_pos: positionView, surf_norm: normalView, dHdxy }); } } export default BumpMapNode; /** * TSL function for creating a bump map node. * * @tsl * @function * @param {Node<float>} textureNode - Represents the bump map data. * @param {?Node<float>} [scaleNode=null] - Controls the intensity of the bump effect. * @returns {BumpMapNode} */ export const bumpMap = /*@__PURE__*/nodeProxy(BumpMapNode).setParameterLength(1, 2);