import * as THREE from 'three'
import {x} from '../xapp/xworld'
import {ShaderFlag, ShaderAlpha} from '../component/visual'
import * as xutils from './xcommon'
import AssetKeepr from './assetkeepr'
import GlUniform from './gluniform'
import {randomParticl} from './shaders/random-particl.glsl'
import {cubeVoxels, cubeVoxelGeom} from './shaders/cube-voxels.glsl'
import {colorLine} from './shaders/color-line.glsl'
import {phongMorph2} from './shaders/color-array.glsl'
import {scaleOrb} from './shaders/orb-scale.glsl'
import {orbGroups} from './shaders/orb-groups.glsl'
import {worldOrbs} from './shaders/orb-world.glsl'
import {thermalTile} from './shaders/tile-thermal.glsl'
import {texPrism} from './shaders/texprism.glsl'
import {boxLayers, xyzLayer2} from './shaders/shape-layers.glsl'
import {cubeTex} from './shaders/sdf-boxtex.glsl'
import {blinkStar, pointGeom} from './shaders/blink-star.glsl'
import {receiveShadow} from './shaders/dir-shadow.glsl'
import {reflectex} from './shaders/reflectex.glsl'
import {testPoint} from './shaders/testpoint.glsl'
import {fragShape} from './shaders/frag-shape.glsl'
/**
* Stub for jsdoc, a collection of common methods
* <br>This class name is all in lower case. X-visual use this convention for a
* collection of common global methods when using jsdoc generating API doc.
* @class xglsl
*/
class xglsl {
/**@constructor */
constructor() {}
}
const shaderPool = {}
/**
* @param {int} flag @see ShaderFlag
* @param {Visual.paras} vparas @see Visual
* @return {object} {vertexShader, fragmentShader}<br>
* The shaders for THREE.ShaderMaterial (using variables supported by Three.js)<br>
* where<br>
* return.vertextShader {string}<br>
* return.vertextShader {string}
* @member xglsl.randomRarticl
* @function */
export function xvShader(flag, vparas = {}, obj3 = {}) {
// TODO share shader progam
var s;
switch (flag) {
case ShaderFlag.randomParticles:
s = randomParticl(vparas);
break;
case ShaderFlag.cubeVoxels:
s = cubeVoxels(vparas);
break;
case ShaderFlag.flameLight:
s = flameLight(vparas);
break;
case ShaderFlag.blinkStar:
s = blinkStar(vparas);
break;
case ShaderFlag.colorArray:
s = phongMorph2(vparas);
break;
case ShaderFlag.scaleOrb:
// this shader needs vertex has a dir attribute
s = scaleOrb(vparas);
break;
case ShaderFlag.worldOrbs:
s = worldOrbs(vparas);
break;
case ShaderFlag.orbGroups:
s = orbGroups(vparas);
break;
case ShaderFlag.tiledOrbs:
// s = tileOrbs(vparas);
s = thermalTile(vparas);
break;
case ShaderFlag.colorLine:
s = colorLine(vparas);
break;
case ShaderFlag.texPrism:
s = texPrism(vparas);
break;
case ShaderFlag.boxLayers:
// s = boxLayers(vparas);
// s = boxRotate(vparas);
s = xyzLayer2(vparas, obj3);
break;
case ShaderFlag.cubeTex:
s = cubeTex(vparas);
break;
case ShaderFlag.receiveShadow:
s = receiveShadow(vparas);
break;
case ShaderFlag.reflectex:
s = reflectex(vparas);
break;
case ShaderFlag.fragShape:
throw new XError('todo');
break;
case ShaderFlag.discard:
s = discardShader(vparas);
break;
case ShaderFlag.testPoints:
default:
// console.warn('xvShader(): unrecognized shader flag: ', flag);
s = testPoint( vparas || new Object() );// as enum doesn't exists, paras also likely undefined
}
if (x.log >= 5)
console.debug(`[5] flag: ${flag.toString(16)}, paras: `,
vparas, '\nshaders: ', s);
return s;
}
/**Is the shader support u_alpha?
* Shaders include AssetType.point, refPoint, GeomCurve, colorArray
* @param {ShaderFlag} shader
* @return {bool}
* @member xglsl.hasUAlpha
* @function
*/
export function hasUAlpha(shader) {
return shader === ShaderFlag.randomParticles ||
shader === ShaderFlag.cubeVoxels ||
shader === ShaderFlag.colorArray ||
shader === ShaderFlag.colorLine;
}
/**@deprecated this function can be completely covered by cubeVoxelGeom().
* Create geometry buffer from target mesh.
* If shader type is randomParticles, the buffer also has attributes color and size.
* @param {Visual.paras} vparas
* @param {TREE.Mesh} meshSrc
* @param {TREE.Mesh} meshTarget
* @return {THREE.BufferGeometry}
* @member xglsl.particlesGeom
* @function
*/
export function particlesGeom (vparas, meshSrc, meshTarget) {
var sizes = [];
var colors = [];
var noise = [];
// var count = meshSrc.count / meshSrc.itemSize; // count = length / 3
var count = meshSrc.count;
for (var c = 0; c < count; c++) {
var color = xutils.randomRGB();
colors.push( color.r, color.g, color.b );
sizes.push( (Math.random() * 2 - 1 ) );
if (vparas && vparas.a_noise)
noise.push( (Math.random() * vparas.noise - vparas.noise / 2 ) );
}
var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', meshSrc.clone(), 3 );
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 )
.setUsage( THREE.DynamicDrawUsage ) );
geometry.setAttribute( 'size', new THREE.Float32BufferAttribute( sizes, 1 )
.setUsage( THREE.DynamicDrawUsage ) );
if (vparas && vparas.a_noise)
geometry.setAttribute( 'a_noise', new THREE.Float32BufferAttribute( noise, 1 )
.setUsage( THREE.DynamicDrawUsage ) );
// TODO case: meshsrc.count != meshTarget.count
if (vparas && (vparas.dest || vparas.a_dest)) {
geometry.setAttribute( 'a_dest', meshTarget.clone(), 3 );
}
return geometry;
}
function discardShader(paras = {}) {
return {
vertexShader: `void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); } `,
fragmentShader: `void main() { discard; }`
};
}
/**Example:
* See docs/design memoe/shader samples
*
* @param {object} vparas visual paras, same as Visual.paras
* @member xglsl.flameLight
* @function
*/
function flameLight(vparas) {
throw XError("TODO");
}
export {cubeVoxelGeom, pointGeom}