Skip to content

Commit

Permalink
make gltf loader support to load points(glitter) (oppenfuture#76)
Browse files Browse the repository at this point in the history
* make gltf loader support to load points(glitter)

* Code style fixes

* fixed points texture bug

* fixed pointSprite shader compile error; added point sprite test

Co-authored-by: mac <[email protected]>

* added depth pass to pointSprite example

* Fix typo

* Fix example page import map and info. Remove roughness mipmapper.

Co-authored-by: WenjieLiuu <[email protected]>
Co-authored-by: mac <[email protected]>
  • Loading branch information
3 people authored Mar 16, 2022
1 parent 2399671 commit c619917
Show file tree
Hide file tree
Showing 5 changed files with 384 additions and 6 deletions.
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"webgl_loader_gltf",
"webgl_loader_gltf_compressed",
"webgl_loader_gltf_sheen",
"webgl_loader_gltf_point_sprite",
"webgl_loader_gltf_transmission",
"webgl_loader_gltf_variants",
"webgl_loader_ifc",
Expand Down
223 changes: 217 additions & 6 deletions examples/jsm/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AdditiveBlending,
AnimationClip,
Bone,
Box3,
Expand Down Expand Up @@ -48,6 +49,7 @@ import {
Quaternion,
QuaternionKeyframeTrack,
RepeatWrapping,
ShaderMaterial,
Skeleton,
SkinnedMesh,
Sphere,
Expand Down Expand Up @@ -368,6 +370,10 @@ class GLTFLoader extends Loader {
extensions[ extensionName ] = new GLTFHighPrecisionNormalExtension();
break;

case EXTENSIONS.OFT_MATERIALS_POINT_SPRITE:
extensions[ extensionName ] = new GLTFMaterialsPointSpriteExtension();
break;

default:

if ( extensionsRequired.indexOf( extensionName ) >= 0 && plugins[ extensionName ] === undefined ) {
Expand Down Expand Up @@ -459,7 +465,8 @@ const EXTENSIONS = {
KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
EXT_TEXTURE_WEBP: 'EXT_texture_webp',
EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',
OFT_TEXTURE_HIGHPRECISION_NORMAL: 'OFT_texture_highPrecisionNormal'
OFT_TEXTURE_HIGHPRECISION_NORMAL: 'OFT_texture_highPrecisionNormal',
OFT_MATERIALS_POINT_SPRITE: 'OFT_materials_pointSprite'
};

/**
Expand Down Expand Up @@ -1811,6 +1818,195 @@ class GLTFHighPrecisionNormalExtension {

}

/**
* Point Sprite Materials Extension
*
* Specification: https://github.com/oppenfuture/glTF/tree/pointSprite/extensions/2.0/Vendor/OFT_materials_pointSprite
*/
class OFTPointSpriteMaterial extends ShaderMaterial {

constructor( params ) {

super( params );
this.type = 'OFTPointSpriteMaterial';

}

}

class GLTFMaterialsPointSpriteExtension {

constructor() {

this.name = EXTENSIONS.OFT_MATERIALS_POINT_SPRITE;

}

getMaterialType() {

return OFTPointSpriteMaterial;

}

extendParams( materialParams, materialDef, parser ) {

const pending = [];

const pointSprite = materialDef.extensions?.OFT_materials_pointSprite;

if ( pointSprite ) {

materialParams.pointSize = pointSprite.pointSize

if ( pointSprite.pointTexture !== undefined ) {

pending.push( parser.assignTexture( materialParams, 'pointTexture', pointSprite.pointTexture ) );

}

}

return Promise.all( pending );

}

createMaterial( materialParams ) {

const uniformsPoint = {

pointSize: { value: materialParams.pointSize * window.devicePixelRatio },
pointTexture: { value: materialParams.pointTexture },
depthTexture: { value: null },
depthBias: { value: 0.01 }

};

const material = new OFTPointSpriteMaterial( {

uniforms: uniformsPoint,
vertexShader: /* glsl */`
attribute float size;
uniform float pointSize;
varying vec4 vColor;
varying float vIntensity;
varying float vRandom;
varying vec4 vMvpPosition;
#define PI 3.14159265359
#define PI2 6.28318530718
const float Threshold = 0.65;
highp float rand( const in vec2 uv ) {
const highp float a = 12.9898, b = 78.233, c = 43758.5453;
highp float dt = dot( uv.xy, vec2( a, b ) ), sn = mod( dt, PI );
return fract(sin(sn) * c);
}
void main() {
vColor.rgb = color.rgb;
vRandom = rand(position.xy);
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
vec3 ViewPosition = - mvPosition.xyz;
vec3 viewDir = normalize(ViewPosition);
vec3 n = normalize(normalMatrix * normal);
float dotNV = dot(viewDir, n);
// cos func to liner func
vIntensity = 1.0 - acos(dotNV);
// map Threshold ~ 1.0 to 0 ~ 1.0
vIntensity = vIntensity < Threshold ? 0.0 : (vIntensity - Threshold) / (1.0 - Threshold);
// sharp the curve
vIntensity = pow(vIntensity, 1.1);
vColor.a = 0.2 + vIntensity * 0.8;
gl_Position = projectionMatrix * mvPosition;
vMvpPosition = gl_Position;
gl_PointSize = ((vRandom * 0.2 + 1.8) * pointSize) * vIntensity * (0.5/-mvPosition.z);
}
`,
fragmentShader: /* glsl */`
precision highp float;
#include <packing>
#define PI 3.14159265359
#define PI2 6.28318530718
uniform sampler2D pointTexture;
uniform sampler2D depthTexture;
uniform sampler2D colorTexture;
uniform float depthBias;
varying vec4 vColor;
varying float vRandom;
varying float vDotNV;
varying float vIntensity;
varying vec4 vMvpPosition;
vec2 rotateUV(vec2 uv, float rotation) {
float mid = 0.5;
return vec2(
cos(rotation) * (uv.x - mid) + sin(rotation) * (uv.y - mid) + mid,
cos(rotation) * (uv.y - mid) - sin(rotation) * (uv.x - mid) + mid
);
}
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
float readDepth( sampler2D depthSampler, vec2 coord ) {
float fragCoordZ = texture2D( depthSampler, coord ).x;
float viewZ = perspectiveDepthToViewZ( fragCoordZ, 0.1, 2.0 );
return viewZToOrthographicDepth( viewZ, 0.1, 2.0 );
}
void main() {
vec3 projCoords = vMvpPosition.xyz / vMvpPosition.w;
projCoords = projCoords * 0.5 + 0.5;
float depth = unpackRGBAToDepth(texture2D(colorTexture, projCoords.xy));
if (projCoords.z - depth >= depthBias) discard;
if (vIntensity <= 0.0) discard;
gl_FragColor = vColor;
vec2 rotateUv = rotateUV(gl_PointCoord, vRandom * vIntensity * PI * 0.6);
rotateUv = clamp(rotateUv, 0.0, 1.0);
gl_FragColor = gl_FragColor * texture2D( pointTexture, rotateUv );
}
`,

blending: AdditiveBlending,
depthTest: false,
transparent: true,
vertexColors: true

} );

return material;

}

}

/*********************************/
/********** INTERPOLATION ********/
/*********************************/
Expand Down Expand Up @@ -3009,7 +3205,12 @@ class GLTFParser {
const useVertexColors = geometry.attributes.color !== undefined;
const useFlatShading = geometry.attributes.normal === undefined;

if ( mesh.isPoints ) {
if ( material.type === 'OFTPointSpriteMaterial' ) {

// TODO: Why need this line?
mesh = mesh.clone();

} else if ( mesh.isPoints ) {

const cacheKey = 'PointsMaterial:' + material.uuid;

Expand Down Expand Up @@ -3134,6 +3335,12 @@ class GLTFParser {
materialType = kmuExtension.getMaterialType();
pending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );

} else if ( materialExtensions[ EXTENSIONS.OFT_MATERIALS_POINT_SPRITE ] ) {

const kmuExtension = extensions[ EXTENSIONS.OFT_MATERIALS_POINT_SPRITE ];
materialType = kmuExtension.getMaterialType();
pending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );

} else {

// Specification:
Expand Down Expand Up @@ -3229,10 +3436,10 @@ class GLTFParser {
if ( extensions[ EXTENSIONS.OFT_TEXTURE_HIGHPRECISION_NORMAL ]
&& materialDef.normalTexture.extensions[ EXTENSIONS.OFT_TEXTURE_HIGHPRECISION_NORMAL ] ) {

var highPrecisionNormalExt = materialDef.normalTexture.extensions[ EXTENSIONS.OFT_TEXTURE_HIGHPRECISION_NORMAL ];
var lowerTexture = highPrecisionNormalExt.lower8BitTexture;
var texCoord = materialDef.normalTexture.texCoord || 0;
var lowerTexCoord = lowerTexture.texCoord || 0;
const highPrecisionNormalExt = materialDef.normalTexture.extensions[ EXTENSIONS.OFT_TEXTURE_HIGHPRECISION_NORMAL ];
const lowerTexture = highPrecisionNormalExt.lower8BitTexture;
const texCoord = materialDef.normalTexture.texCoord || 0;
const lowerTexCoord = lowerTexture.texCoord || 0;
// The texCoord property of lower8BitTexture must be the same as the texCoord of normalTexture
if ( texCoord !== lowerTexCoord ) {

Expand Down Expand Up @@ -3282,6 +3489,10 @@ class GLTFParser {

material = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );

} else if ( materialType === OFTPointSpriteMaterial ) {

material = extensions[ EXTENSIONS.OFT_MATERIALS_POINT_SPRITE ].createMaterial( materialParams );

} else {

material = new materialType( materialParams );
Expand Down
Binary file added examples/models/gltf/glitter.glb
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit c619917

Please sign in to comment.