three-stdlib
Version:
stand-alone library of threejs examples
137 lines (127 loc) • 4.7 kB
JavaScript
import { Mesh, IcosahedronGeometry, ShaderMaterial, DoubleSide } from "three";
import { version } from "../_polyfill/constants.js";
const isCubeTexture = (def) => def && def.isCubeTexture;
class GroundProjectedEnv extends Mesh {
constructor(texture, options) {
var _a, _b;
const isCubeMap = isCubeTexture(texture);
const w = (_b = isCubeMap ? (_a = texture.image[0]) == null ? void 0 : _a.width : texture.image.width) != null ? _b : 1024;
const cubeSize = w / 4;
const _lodMax = Math.floor(Math.log2(cubeSize));
const _cubeSize = Math.pow(2, _lodMax);
const width = 3 * Math.max(_cubeSize, 16 * 7);
const height = 4 * _cubeSize;
const defines = [
isCubeMap ? "#define ENVMAP_TYPE_CUBE" : "",
`
`
`
];
const vertexShader = (
/* glsl */
`
varying vec3 vWorldPosition;
void main()
{
vec4 worldPosition = ( modelMatrix * vec4( position, 1.0 ) );
vWorldPosition = worldPosition.xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
);
const fragmentShader = defines.join("\n") + /* glsl */
`
varying vec3 vWorldPosition;
uniform float radius;
uniform float height;
uniform float angle;
uniform samplerCube map;
uniform sampler2D map;
// From: https://www.shadertoy.com/view/4tsBD7
float diskIntersectWithBackFaceCulling( vec3 ro, vec3 rd, vec3 c, vec3 n, float r )
{
float d = dot ( rd, n );
if( d > 0.0 ) { return 1e6; }
vec3 o = ro - c;
float t = - dot( n, o ) / d;
vec3 q = o + rd * t;
return ( dot( q, q ) < r * r ) ? t : 1e6;
}
// From: https://www.iquilezles.org/www/articles/intersectors/intersectors.htm
float sphereIntersect( vec3 ro, vec3 rd, vec3 ce, float ra )
{
vec3 oc = ro - ce;
float b = dot( oc, rd );
float c = dot( oc, oc ) - ra * ra;
float h = b * b - c;
if( h < 0.0 ) { return -1.0; }
h = sqrt( h );
return - b + h;
}
vec3 project()
{
vec3 p = normalize( vWorldPosition );
vec3 camPos = cameraPosition;
camPos.y -= height;
float intersection = sphereIntersect( camPos, p, vec3( 0.0 ), radius );
if( intersection > 0.0 ) {
vec3 h = vec3( 0.0, - height, 0.0 );
float intersection2 = diskIntersectWithBackFaceCulling( camPos, p, h, vec3( 0.0, 1.0, 0.0 ), radius );
p = ( camPos + min( intersection, intersection2 ) * p ) / radius;
} else {
p = vec3( 0.0, 1.0, 0.0 );
}
return p;
}
void main()
{
vec3 projectedWorldPosition = project();
vec3 outcolor = textureCube( map, projectedWorldPosition ).rgb;
vec3 direction = normalize( projectedWorldPosition );
vec2 uv = equirectUv( direction );
vec3 outcolor = texture2D( map, uv ).rgb;
gl_FragColor = vec4( outcolor, 1.0 );
}
`;
const uniforms = {
map: { value: texture },
height: { value: (options == null ? void 0 : options.height) || 15 },
radius: { value: (options == null ? void 0 : options.radius) || 100 }
};
const geometry = new IcosahedronGeometry(1, 16);
const material = new ShaderMaterial({
uniforms,
fragmentShader,
vertexShader,
side: DoubleSide
});
super(geometry, material);
}
set radius(radius) {
this.material.uniforms.radius.value = radius;
}
get radius() {
return this.material.uniforms.radius.value;
}
set height(height) {
this.material.uniforms.height.value = height;
}
get height() {
return this.material.uniforms.height.value;
}
}
export {
GroundProjectedEnv
};
//# sourceMappingURL=GroundProjectedEnv.js.map