hefeihvac_java/node_modules/echarts-gl/lib/effect/NormalPass.js

197 lines
6.5 KiB
JavaScript
Raw Permalink Normal View History

2024-04-07 18:15:00 +08:00
// NormalPass will generate normal and depth data.
// TODO Animation
import Texture2D from 'claygl/src/Texture2D';
import Texture from 'claygl/src/Texture';
import Shader from 'claygl/src/Shader';
import FrameBuffer from 'claygl/src/FrameBuffer';
import Material from 'claygl/src/Material';
import Pass from 'claygl/src/compositor/Pass';
import textureUtil from 'claygl/src/util/texture';
import normalGLSL from '../util/shader/normal.glsl.js';
Shader.import(normalGLSL);
function attachTextureToSlot(renderer, program, symbol, texture, slot) {
var gl = renderer.gl;
program.setUniform(gl, '1i', symbol, slot);
gl.activeTexture(gl.TEXTURE0 + slot); // Maybe texture is not loaded yet;
if (texture.isRenderable()) {
texture.bind(renderer);
} else {
// Bind texture to null
texture.unbind(renderer);
}
} // TODO Use globalShader insteadof globalMaterial?
function getBeforeRenderHook(renderer, defaultNormalMap, defaultBumpMap, defaultRoughnessMap, normalMaterial) {
var previousNormalMap;
var previousBumpMap;
var previousRoughnessMap;
var previousRenderable;
var gl = renderer.gl;
return function (renderable, normalMaterial, prevNormalMaterial) {
// Material not change
if (previousRenderable && previousRenderable.material === renderable.material) {
return;
}
var material = renderable.material;
var program = renderable.__program;
var roughness = material.get('roughness');
if (roughness == null) {
roughness = 1;
}
var normalMap = material.get('normalMap') || defaultNormalMap;
var roughnessMap = material.get('roughnessMap');
var bumpMap = material.get('bumpMap');
var uvRepeat = material.get('uvRepeat');
var uvOffset = material.get('uvOffset');
var detailUvRepeat = material.get('detailUvRepeat');
var detailUvOffset = material.get('detailUvOffset');
var useBumpMap = !!bumpMap && material.isTextureEnabled('bumpMap');
var useRoughnessMap = !!roughnessMap && material.isTextureEnabled('roughnessMap');
var doubleSide = material.isDefined('fragment', 'DOUBLE_SIDED');
bumpMap = bumpMap || defaultBumpMap;
roughnessMap = roughnessMap || defaultRoughnessMap;
if (prevNormalMaterial !== normalMaterial) {
normalMaterial.set('normalMap', normalMap);
normalMaterial.set('bumpMap', bumpMap);
normalMaterial.set('roughnessMap', roughnessMap);
normalMaterial.set('useBumpMap', useBumpMap);
normalMaterial.set('useRoughnessMap', useRoughnessMap);
normalMaterial.set('doubleSide', doubleSide);
uvRepeat != null && normalMaterial.set('uvRepeat', uvRepeat);
uvOffset != null && normalMaterial.set('uvOffset', uvOffset);
detailUvRepeat != null && normalMaterial.set('detailUvRepeat', detailUvRepeat);
detailUvOffset != null && normalMaterial.set('detailUvOffset', detailUvOffset);
normalMaterial.set('roughness', roughness);
} else {
program.setUniform(gl, '1f', 'roughness', roughness);
if (previousNormalMap !== normalMap) {
attachTextureToSlot(renderer, program, 'normalMap', normalMap, 0);
}
if (previousBumpMap !== bumpMap && bumpMap) {
attachTextureToSlot(renderer, program, 'bumpMap', bumpMap, 1);
}
if (previousRoughnessMap !== roughnessMap && roughnessMap) {
attachTextureToSlot(renderer, program, 'roughnessMap', roughnessMap, 2);
}
if (uvRepeat != null) {
program.setUniform(gl, '2f', 'uvRepeat', uvRepeat);
}
if (uvOffset != null) {
program.setUniform(gl, '2f', 'uvOffset', uvOffset);
}
if (detailUvRepeat != null) {
program.setUniform(gl, '2f', 'detailUvRepeat', detailUvRepeat);
}
if (detailUvOffset != null) {
program.setUniform(gl, '2f', 'detailUvOffset', detailUvOffset);
}
program.setUniform(gl, '1i', 'useBumpMap', +useBumpMap);
program.setUniform(gl, '1i', 'useRoughnessMap', +useRoughnessMap);
program.setUniform(gl, '1i', 'doubleSide', +doubleSide);
}
previousNormalMap = normalMap;
previousBumpMap = bumpMap;
previousRoughnessMap = roughnessMap;
previousRenderable = renderable;
};
}
function NormalPass(opt) {
opt = opt || {};
this._depthTex = new Texture2D({
format: Texture.DEPTH_COMPONENT,
type: Texture.UNSIGNED_INT
});
this._normalTex = new Texture2D({
type: Texture.HALF_FLOAT
});
this._framebuffer = new FrameBuffer();
this._framebuffer.attach(this._normalTex);
this._framebuffer.attach(this._depthTex, FrameBuffer.DEPTH_ATTACHMENT);
this._normalMaterial = new Material({
shader: new Shader(Shader.source('ecgl.normal.vertex'), Shader.source('ecgl.normal.fragment'))
});
this._normalMaterial.enableTexture(['normalMap', 'bumpMap', 'roughnessMap']);
this._defaultNormalMap = textureUtil.createBlank('#000');
this._defaultBumpMap = textureUtil.createBlank('#000');
this._defaultRoughessMap = textureUtil.createBlank('#000');
this._debugPass = new Pass({
fragment: Shader.source('clay.compositor.output')
});
this._debugPass.setUniform('texture', this._normalTex);
this._debugPass.material.undefine('fragment', 'OUTPUT_ALPHA');
}
NormalPass.prototype.getDepthTexture = function () {
return this._depthTex;
};
NormalPass.prototype.getNormalTexture = function () {
return this._normalTex;
};
NormalPass.prototype.update = function (renderer, scene, camera) {
var width = renderer.getWidth();
var height = renderer.getHeight();
var depthTexture = this._depthTex;
var normalTexture = this._normalTex;
var normalMaterial = this._normalMaterial;
depthTexture.width = width;
depthTexture.height = height;
normalTexture.width = width;
normalTexture.height = height;
var opaqueList = scene.getRenderList(camera).opaque;
this._framebuffer.bind(renderer);
renderer.gl.clearColor(0, 0, 0, 0);
renderer.gl.clear(renderer.gl.COLOR_BUFFER_BIT | renderer.gl.DEPTH_BUFFER_BIT);
renderer.gl.disable(renderer.gl.BLEND);
renderer.renderPass(opaqueList, camera, {
getMaterial: function () {
return normalMaterial;
},
ifRender: function (object) {
return object.renderNormal;
},
beforeRender: getBeforeRenderHook(renderer, this._defaultNormalMap, this._defaultBumpMap, this._defaultRoughessMap, this._normalMaterial),
sort: renderer.opaqueSortCompare
});
this._framebuffer.unbind(renderer);
};
NormalPass.prototype.renderDebug = function (renderer) {
this._debugPass.render(renderer);
};
NormalPass.prototype.dispose = function (renderer) {
this._depthTex.dispose(renderer);
this._normalTex.dispose(renderer);
};
export default NormalPass;