-
-
Notifications
You must be signed in to change notification settings - Fork 35.2k
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
WebGLRenderer: Fix setRenderTarget()'s activeMipmapLevel #26347
Merged
Merged
Changes from 6 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
65e061f
Ability to set the mip levels of a texture as a render target
makovkins e593479
Render to texture's mip levels example
makovkins b771ea8
Render to texture's mip levels example: added a screenshot, fixed errors
makovkins be22ea9
Render to texture's mip levels example: added the example to json files
makovkins 12ebb60
Render to texture's mip levels example: updated the screenshot
makovkins ffc1258
Update webgl_materials_cubemap_render_to_mipmaps.html
Mugen87 f90ffed
Update WebGLRenderer.js
Mugen87 7d5d622
Update WebGLRenderer.js
Mugen87 7cf7870
Update WebGLRenderer.js
Mugen87 File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
278 changes: 278 additions & 0 deletions
278
examples/webgl_materials_cubemap_render_to_mipmaps.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<title>three.js webgl - materials - cubemap mipmaps</title> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | ||
<link type="text/css" rel="stylesheet" href="main.css"> | ||
</head> | ||
<body> | ||
|
||
<div id="container"></div> | ||
<div id="info"> | ||
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - rendering to cubemap mip levels demo.<br/> | ||
Left: original cubemap<br/> | ||
Right: generated cubemap<br/> | ||
</div> | ||
|
||
<!-- Import maps polyfill --> | ||
<!-- Remove this when import maps will be widely supported --> | ||
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | ||
|
||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"three": "../build/three.module.js", | ||
"three/addons/": "./jsm/" | ||
} | ||
} | ||
</script> | ||
|
||
<script type="module"> | ||
|
||
import * as THREE from 'three'; | ||
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; | ||
|
||
let container; | ||
let camera, scene, renderer; | ||
|
||
const CubemapFilterShader = { | ||
uniforms: { | ||
cubeTexture: { value: null }, | ||
mipIndex: { value: 0 }, | ||
}, | ||
|
||
vertexShader: /* glsl */ ` | ||
|
||
varying vec3 vWorldDirection; | ||
|
||
#include <common> | ||
|
||
void main() { | ||
vWorldDirection = transformDirection(position, modelMatrix); | ||
#include <begin_vertex> | ||
#include <project_vertex> | ||
gl_Position.z = gl_Position.w; // set z to camera.far | ||
} | ||
|
||
`, | ||
|
||
fragmentShader: /* glsl */ ` | ||
|
||
uniform samplerCube cubeTexture; | ||
varying vec3 vWorldDirection; | ||
|
||
uniform float mipIndex; | ||
|
||
#include <common> | ||
|
||
void main() { | ||
vec3 cubeCoordinates = normalize(vWorldDirection); | ||
|
||
// Colorize mip levels | ||
vec4 color = vec4(1.0, 0.0, 0.0, 1.0); | ||
if (mipIndex == 0.0) color.rgb = vec3(1.0, 1.0, 1.0); | ||
else if (mipIndex == 1.0) color.rgb = vec3(0.0, 0.0, 1.0); | ||
else if (mipIndex == 2.0) color.rgb = vec3(0.0, 1.0, 1.0); | ||
else if (mipIndex == 3.0) color.rgb = vec3(0.0, 1.0, 0.0); | ||
else if (mipIndex == 4.0) color.rgb = vec3(1.0, 1.0, 0.0); | ||
|
||
gl_FragColor = textureCube(cubeTexture, cubeCoordinates, 0.0) * color; | ||
} | ||
|
||
`, | ||
}; | ||
|
||
|
||
init(); | ||
animate(); | ||
|
||
|
||
async function loadCubeTexture( urls ) { | ||
|
||
return new Promise( function ( resolve ) { | ||
|
||
new THREE.CubeTextureLoader().load( urls, function ( cubeTexture ) { | ||
|
||
resolve( cubeTexture ); | ||
|
||
} ); | ||
|
||
|
||
} ); | ||
|
||
} | ||
|
||
function allocateCubemapRenderTarget( cubeMapSize ) { | ||
|
||
const params = { | ||
magFilter: THREE.LinearFilter, | ||
minFilter: THREE.LinearMipMapLinearFilter, | ||
generateMipmaps: false, | ||
type: THREE.HalfFloatType, | ||
format: THREE.RGBAFormat, | ||
colorSpace: THREE.LinearSRGBColorSpace, | ||
depthBuffer: false, | ||
}; | ||
|
||
const rt = new THREE.WebGLCubeRenderTarget( cubeMapSize, params ); | ||
|
||
const mipLevels = Math.log( cubeMapSize ) * Math.LOG2E + 1.0; | ||
for ( let i = 0; i < mipLevels; i ++ ) rt.texture.mipmaps.push( {} ); | ||
|
||
rt.texture.mapping = THREE.CubeReflectionMapping; | ||
return rt; | ||
|
||
} | ||
|
||
function renderToCubeTexture( cubeMapRenderTarget, sourceCubeTexture ) { | ||
|
||
const cameras = []; | ||
|
||
for ( let i = 0; i < 6; i ++ ) { | ||
|
||
// negative fov is not an error | ||
cameras.push( new THREE.PerspectiveCamera( - 90, 1, 1, 10 ) ); | ||
|
||
} | ||
|
||
cameras[ 0 ].up.set( 0, 1, 0 ); | ||
cameras[ 0 ].lookAt( 1, 0, 0 ); | ||
cameras[ 1 ].up.set( 0, 1, 0 ); | ||
cameras[ 1 ].lookAt( - 1, 0, 0 ); | ||
cameras[ 2 ].up.set( 0, 0, - 1 ); | ||
cameras[ 2 ].lookAt( 0, 1, 0 ); | ||
cameras[ 3 ].up.set( 0, 0, 1 ); | ||
cameras[ 3 ].lookAt( 0, - 1, 0 ); | ||
cameras[ 4 ].up.set( 0, 1, 0 ); | ||
cameras[ 4 ].lookAt( 0, 0, 1 ); | ||
cameras[ 5 ].up.set( 0, 1, 0 ); | ||
cameras[ 5 ].lookAt( 0, 0, - 1 ); | ||
|
||
for ( let i = 0; i < 6; i ++ ) cameras[ i ].updateMatrixWorld(); | ||
|
||
const geometry = new THREE.BoxGeometry( 5, 5, 5 ); | ||
|
||
const material = new THREE.ShaderMaterial( { | ||
name: 'FilterCubemap', | ||
uniforms: THREE.UniformsUtils.clone( CubemapFilterShader.uniforms ), | ||
vertexShader: CubemapFilterShader.vertexShader, | ||
fragmentShader: CubemapFilterShader.fragmentShader, | ||
side: THREE.BackSide, | ||
blending: THREE.NoBlending, | ||
} ); | ||
|
||
material.uniforms.cubeTexture.value = sourceCubeTexture; | ||
|
||
const mesh = new THREE.Mesh( geometry, material ); | ||
|
||
const currentRenderTarget = renderer.getRenderTarget(); | ||
const currentXrEnabled = renderer.xr.enabled; | ||
renderer.xr.enabled = false; | ||
|
||
for ( let faceIndex = 0; faceIndex < 6; faceIndex ++ ) { | ||
|
||
let mipIndex = 0; | ||
let mipSize = cubeMapRenderTarget.width; | ||
|
||
// Render to each texture mip level | ||
while ( mipSize >= 1 ) { | ||
|
||
cubeMapRenderTarget.viewport.set( 0, 0, mipSize, mipSize ); | ||
renderer.setRenderTarget( cubeMapRenderTarget, faceIndex, mipIndex ); | ||
material.uniforms.mipIndex.value = mipIndex; | ||
material.needsUpdate = true; | ||
renderer.render( mesh, cameras[ faceIndex ] ); | ||
mipSize >>= 1; | ||
mipIndex ++; | ||
|
||
} | ||
|
||
} | ||
|
||
renderer.setRenderTarget( currentRenderTarget ); | ||
renderer.xr.enabled = currentXrEnabled; | ||
|
||
mesh.geometry.dispose(); | ||
mesh.material.dispose(); | ||
|
||
} | ||
|
||
function init() { | ||
|
||
container = document.createElement( 'div' ); | ||
document.body.appendChild( container ); | ||
|
||
// Create renderer | ||
renderer = new THREE.WebGLRenderer( { antialias: true } ); | ||
renderer.setPixelRatio( window.devicePixelRatio ); | ||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
container.appendChild( renderer.domElement ); | ||
|
||
scene = new THREE.Scene(); | ||
|
||
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 ); | ||
camera.position.z = 500; | ||
|
||
// Create controls | ||
const controls = new OrbitControls( camera, renderer.domElement ); | ||
controls.minPolarAngle = Math.PI / 4; | ||
controls.maxPolarAngle = Math.PI / 1.5; | ||
|
||
window.addEventListener( 'resize', onWindowResize ); | ||
|
||
// Load a cube texture | ||
const r = 'textures/cube/Park3Med/'; | ||
const urls = [ | ||
r + 'px.jpg', r + 'nx.jpg', | ||
r + 'py.jpg', r + 'ny.jpg', | ||
r + 'pz.jpg', r + 'nz.jpg' | ||
]; | ||
|
||
loadCubeTexture( urls ).then( ( cubeTexture ) => { | ||
|
||
// Allocate a cube map render target | ||
const cubeMapRenderTarget = allocateCubemapRenderTarget( 512 ); | ||
|
||
// Render to all the mip levels of cubeMapRenderTarget | ||
renderToCubeTexture( cubeMapRenderTarget, cubeTexture ); | ||
|
||
// Create geometry | ||
const sphere = new THREE.SphereGeometry( 100, 128, 128 ); | ||
let material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: cubeTexture } ); | ||
|
||
let mesh = new THREE.Mesh( sphere, material ); | ||
mesh.position.set( - 100, 0, 0 ); | ||
scene.add( mesh ); | ||
|
||
material = material.clone(); | ||
material.envMap = cubeMapRenderTarget.texture; | ||
|
||
mesh = new THREE.Mesh( sphere, material ); | ||
mesh.position.set( 100, 0, 0 ); | ||
scene.add( mesh ); | ||
|
||
} ); | ||
|
||
} | ||
|
||
function onWindowResize() { | ||
|
||
camera.aspect = window.innerWidth / window.innerHeight; | ||
camera.updateProjectionMatrix(); | ||
|
||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
|
||
} | ||
|
||
function animate() { | ||
|
||
requestAnimationFrame( animate ); | ||
renderer.render( scene, camera ); | ||
|
||
} | ||
|
||
</script> | ||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mrdoob Explicitly defining the mipmaps of the cube render target like demonstrated here triggers the new code path.