Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples: Add ground projected env map #24311

Merged
merged 19 commits into from
Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
"webgl_materials_displacementmap",
"webgl_materials_envmaps",
"webgl_materials_envmaps_exr",
"webgl_materials_envmaps_ground-projected",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to replace - in the example name with _.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that would make the sidebar section title materials / envmaps / ground / projected and not materials / envmaps / ground-projected

"webgl_materials_envmaps_hdr",
"webgl_materials_lightmap",
"webgl_materials_matcap",
Expand Down
186 changes: 186 additions & 0 deletions examples/jsm/objects/GroundProjectedEnv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import { Mesh, IcosahedronGeometry, ShaderMaterial, DoubleSide } from 'three';

/**
* Ground projected env map adapted from @react-three/drei.
* https://github.com/pmndrs/drei/blob/master/src/core/Environment.tsx
*/
export class GroundProjectedEnv extends Mesh {

constructor( texture, options ) {

const isCubeMap = texture.isCubeTexture;
const w =
( isCubeMap ? texture.image[ 0 ]?.width : texture.image.width ) ?? 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' : '',
`#define CUBEUV_TEXEL_WIDTH ${1.0 / width}`,
`#define CUBEUV_TEXEL_HEIGHT ${1.0 / height}`,
`#define CUBEUV_MAX_MIP ${_lodMax}.0`,
];

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 */ `
#define ENVMAP_TYPE_CUBE_UV

varying vec3 vWorldPosition;

uniform float radius;
uniform float height;
uniform float angle;

#ifdef ENVMAP_TYPE_CUBE

uniform samplerCube map;

#else

uniform sampler2D map;

#endif

// 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;

}

#include <common>
#include <cube_uv_reflection_fragment>

void main()
{

vec3 projectedWorldPosition = project();

#ifdef ENVMAP_TYPE_CUBE

vec3 outcolor = textureCube( map, projectedWorldPosition ).rgb;

#else

vec3 direction = normalize( projectedWorldPosition );
vec2 uv = equirectUv( direction );
vec3 outcolor = texture2D( map, uv ).rgb;

#endif

gl_FragColor = vec4( outcolor, 1.0 );

#include <tonemapping_fragment>
#include <encodings_fragment>

}
`;

const uniforms = {
map: { value: texture },
height: { value: options?.height || 15 },
radius: { value: 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;

}

}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/textures/cube/lake/nx.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/textures/cube/lake/ny.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/textures/cube/lake/nz.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/textures/cube/lake/px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/textures/cube/lake/py.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/textures/cube/lake/pz.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading