From fa14c786b1568c5071c0fcbea26d3b4c5ebe30fc Mon Sep 17 00:00:00 2001 From: Dusan Bosnjak Date: Tue, 29 May 2018 20:58:56 -0700 Subject: [PATCH 1/4] add example --- examples/files.js | 1 + ...webgl_materials_extended_multiple_uvs.html | 307 ++++++++++++++++++ 2 files changed, 308 insertions(+) create mode 100644 examples/webgl_materials_extended_multiple_uvs.html diff --git a/examples/files.js b/examples/files.js index 6b0661895c51c1..316ff96616b9b6 100644 --- a/examples/files.js +++ b/examples/files.js @@ -158,6 +158,7 @@ var files = { "webgl_materials_envmaps", "webgl_materials_envmaps_exr", "webgl_materials_envmaps_hdr", + "webgl_materials_extended_multiple_uvs", "webgl_materials_grass", "webgl_materials_lightmap", "webgl_materials_nodes", diff --git a/examples/webgl_materials_extended_multiple_uvs.html b/examples/webgl_materials_extended_multiple_uvs.html new file mode 100644 index 00000000000000..f64d636b90a663 --- /dev/null +++ b/examples/webgl_materials_extended_multiple_uvs.html @@ -0,0 +1,307 @@ + + + + three.js webgl - instancing - lambert shader + + + + + + +
+
+ three.js - instancing - lambert shader + +
+ + + + + + + + + + + + + + + From d560f0de7817298313db3d98681fb2f936785be1 Mon Sep 17 00:00:00 2001 From: Dusan Bosnjak Date: Tue, 29 May 2018 23:13:18 -0700 Subject: [PATCH 2/4] add gui and props --- ...webgl_materials_extended_multiple_uvs.html | 107 ++++++++++++++---- 1 file changed, 84 insertions(+), 23 deletions(-) diff --git a/examples/webgl_materials_extended_multiple_uvs.html b/examples/webgl_materials_extended_multiple_uvs.html index f64d636b90a663..90d8a9f7a430f7 100644 --- a/examples/webgl_materials_extended_multiple_uvs.html +++ b/examples/webgl_materials_extended_multiple_uvs.html @@ -59,22 +59,44 @@ var renderer, scene, camera, controls, materials, mesh; - var stats; + var stats, gui, guiProps; var guiData = { material: 'MeshStandard' } init(); - initGUI(); animate(); + var guis = [] + function onMaterialChange( value ) { + while(guis.length){ + guiProps.remove(guis.pop()) + } mesh.material = materials[value] + var u = function(){ + for (var i = mesh.material.userData.extraProps.length - 1; i >= 0; i--) { + var n = mesh.material.userData.extraProps[i] + guis.push( guiProps.add(mesh.material[`${n}Offset`],'x', 0, 5).name(`${n}Offset U`) ) + guis.push( guiProps.add(mesh.material[`${n}Offset`],'y', 0, 5).name(`${n}Offset V`) ) + guis.push( guiProps.add(mesh.material[`${n}Scale`],'x', 0, 5).name(`${n}Scale U`) ) + guis.push( guiProps.add(mesh.material[`${n}Scale`],'y', 0, 5).name(`${n}Scale V`) ) + } + } + + if(!mesh.material.userData.extraProps){ + setTimeout(u,100) + } else { + u() + } + } + + function initGUI(){ - var gui = new dat.GUI(); + gui = new dat.GUI() gui.add( @@ -85,11 +107,16 @@ 'MeshStandard', ] - ).onChange(onMaterialChange); + ).onChange(onMaterialChange) + + guiProps = gui.addFolder('texture controls') + guiProps.open() onMaterialChange(guiData.material) + } + function init() { //share with other extended examples? @@ -161,7 +188,10 @@ texture.mapping = THREE.SphericalReflectionMapping; texture.encoding = THREE.sRGBEncoding; - if ( mesh ) mesh.material.needsUpdate = true; + + mesh = new THREE.Mesh( new THREE.SphereGeometry(10,32,16), materials[guiData.material] ) + + scene.add( mesh ); } ); @@ -171,15 +201,17 @@ MeshPhong: new THREE.MeshPhongMaterial({ color: 0xffb54a, envMap: envMap, - fog: true + fog: true, + transparent: true }), MeshStandard: new THREE.MeshStandardMaterial({ color: 0xffb54a, envMap: envMap, metalness: 1, - roughness: 0, - fog: true + roughness: 1, + fog: true, + transparent: true }), } @@ -228,19 +260,53 @@ var level = 1 + const extraUniforms = {} + this.userData.extraUniforms = extraUniforms + + const extraProps = [] + this.userData.extraProps = extraProps + + var _this = this + function replaceMaps( string ){ function replace( match, mapName ) { if(!validMaps[mapName]) return match - var uniformName = `u_${mapName}ScaleOffset` - // shader.uniforms[uniformName] = { value: new THREE.Vector4(1,1,0,0) } - shader.uniforms[uniformName] = { value: new THREE.Vector4(level,level,level*0.25,level*0.25) } + + var uniformNameScale = `u_${mapName}Scale` + var uniformNameOffset = `u_${mapName}Offset` + + var uniformScale = { value: new THREE.Vector2(level,level) } + var uniformOffset = { value: new THREE.Vector2(level*0.25,level*0.25) } + + shader.uniforms[uniformNameScale] = uniformScale + extraUniforms[uniformNameScale ] = uniformScale + shader.uniforms[uniformNameOffset] = uniformOffset + extraUniforms[uniformNameOffset ] = uniformOffset + level++ - prependUniforms += `uniform vec4 ${uniformName};\n` - - var replace = `texture2D( ${mapName}, vUv * ${uniformName}.xy + ${uniformName}.zw )` + prependUniforms += `uniform vec2 ${uniformNameScale};\n` + prependUniforms += `uniform vec2 ${uniformNameOffset};\n` + + extraProps.push(mapName) + var foo = { + [`${mapName}Scale`]: { + get: function(){ return extraUniforms[uniformNameScale].value }, + set: function(val){ extraUniforms[uniformNameScale].value.copy(val) } + }, + [`${mapName}Offset`]: { + get: function(){ return extraUniforms[uniformNameOffset].value }, + set: function(val){ extraUniforms[uniformNameOffset].value.copy(val) } + } + } + Object.defineProperties( + _this, + foo + ) + + var replace = `texture2D( ${mapName}, vUv * ${uniformNameScale} + ${uniformNameOffset} )` return replaceMaps( replace ) } @@ -252,6 +318,8 @@ shader.fragmentShader = prependUniforms + shader.fragmentShader + //init here so it can take params + if(!gui) initGUI() } //extend these materials @@ -262,20 +330,13 @@ for ( var map in validMaps ){ if(material[map] === null) { material[map] = texture - console.log(material[map]) } } - materials[materialName].onBeforeCompile = onBeforeCompile + material.onBeforeCompile = onBeforeCompile.bind( material ) } - - mesh = new THREE.Mesh( new THREE.SphereGeometry(10,32,16), materials[guiData.material] ) - - - scene.add( mesh ); - } function onWindowResize( event ) { @@ -291,7 +352,7 @@ requestAnimationFrame( animate ); - mesh.rotation.y += 0.005 + if(mesh) mesh.rotation.y += 0.005 stats.update(); From cc87cad3027d39456658e37c6df8f897401ab67f Mon Sep 17 00:00:00 2001 From: Dusan Bosnjak Date: Wed, 30 May 2018 01:10:18 -0700 Subject: [PATCH 3/4] add transform --- ...webgl_materials_extended_multiple_uvs.html | 152 +++++++++++------- 1 file changed, 91 insertions(+), 61 deletions(-) diff --git a/examples/webgl_materials_extended_multiple_uvs.html b/examples/webgl_materials_extended_multiple_uvs.html index 90d8a9f7a430f7..a6b11924d76a84 100644 --- a/examples/webgl_materials_extended_multiple_uvs.html +++ b/examples/webgl_materials_extended_multiple_uvs.html @@ -59,8 +59,8 @@ var renderer, scene, camera, controls, materials, mesh; - var stats, gui, guiProps; - var guiData = { material: 'MeshStandard' } + var stats, gui, guiProps, guiMap; + var guiData = { material: 'MeshStandard', map: 'map' } init(); animate(); @@ -68,20 +68,37 @@ var guis = [] function onMaterialChange( value ) { - + + if(guiMap) gui.remove(guiMap) + + guiData.map = 'map' + + mesh.material = materials[value] + + guiMap = gui.add( guiData, 'map', mesh.material.userData.extraProps ).onChange(onPropChange) + + onPropChange('map') + } + + function onPropChange(value){ + while(guis.length){ - guiProps.remove(guis.pop()) + gui.remove(guis.pop()) } - mesh.material = materials[value] var u = function(){ - for (var i = mesh.material.userData.extraProps.length - 1; i >= 0; i--) { - var n = mesh.material.userData.extraProps[i] - guis.push( guiProps.add(mesh.material[`${n}Offset`],'x', 0, 5).name(`${n}Offset U`) ) - guis.push( guiProps.add(mesh.material[`${n}Offset`],'y', 0, 5).name(`${n}Offset V`) ) - guis.push( guiProps.add(mesh.material[`${n}Scale`],'x', 0, 5).name(`${n}Scale U`) ) - guis.push( guiProps.add(mesh.material[`${n}Scale`],'y', 0, 5).name(`${n}Scale V`) ) - } + + let n = guiData.map + + var texUpdate = mesh.material[`${n}UpdateMatrix`] + + guis.push( gui.add(mesh.material[`${n}Offset`],'x', 0, 5).name(`${n}Offset U`).onChange(texUpdate)) + guis.push( gui.add(mesh.material[`${n}Offset`],'y', 0, 5).name(`${n}Offset V`).onChange(texUpdate)) + guis.push( gui.add(mesh.material[`${n}Scale`],'x', 0, 5).name(`${n}Scale U`).onChange(texUpdate)) + guis.push( gui.add(mesh.material[`${n}Scale`],'y', 0, 5).name(`${n}Scale V`).onChange(texUpdate)) + guis.push( gui.add(mesh.material, `${n}Rotation`, 0, Math.PI * 2).name(`${n}Rotation`).onChange(texUpdate)) + + guis.push( gui.add(mesh.material,'transparent') ) } if(!mesh.material.userData.extraProps){ @@ -89,11 +106,9 @@ } else { u() } - } - function initGUI(){ gui = new dat.GUI() @@ -109,9 +124,6 @@ ).onChange(onMaterialChange) - guiProps = gui.addFolder('texture controls') - guiProps.open() - onMaterialChange(guiData.material) } @@ -179,7 +191,8 @@ // ----------------------------------------------------------------------------- - // example + // some textures ---------------------------------------------------------------------- + var texture = new THREE.TextureLoader().load( `textures/roughness_map.jpg` ) texture.wrapS = texture.wrapT = THREE.RepeatWrapping @@ -195,6 +208,20 @@ } ); + // example ---------------------------------------------------------------------- + var setUvTransform = function ( tx, ty, sx, sy, rotation, cx, cy ) { + + var c = Math.cos( rotation ); + var s = Math.sin( rotation ); + + this.set( + sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, + - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, + 0, 0, 0 + ); + + } + //create an instance of various types of materials materials = { @@ -253,19 +280,10 @@ //look for maps that are mapped with vUv var mapRegex = /texture2D\( (.*Map|map), vUv \)/gm - + //TODO: refactor this so props are created syncroncously (and props) var onBeforeCompile = function ( shader ) { var prependUniforms = '' - - var level = 1 - - const extraUniforms = {} - this.userData.extraUniforms = extraUniforms - - const extraProps = [] - this.userData.extraProps = extraProps - var _this = this function replaceMaps( string ){ @@ -274,39 +292,14 @@ if(!validMaps[mapName]) return match + let uniformName = `u_${mapName}Transform` - var uniformNameScale = `u_${mapName}Scale` - var uniformNameOffset = `u_${mapName}Offset` - - var uniformScale = { value: new THREE.Vector2(level,level) } - var uniformOffset = { value: new THREE.Vector2(level*0.25,level*0.25) } - - shader.uniforms[uniformNameScale] = uniformScale - extraUniforms[uniformNameScale ] = uniformScale - shader.uniforms[uniformNameOffset] = uniformOffset - extraUniforms[uniformNameOffset ] = uniformOffset + prependUniforms += `uniform mat3 ${uniformName};\n` + shader.uniforms[uniformName] = _this.userData.extraUniforms[uniformName] + shader.uniforms[uniformName].name = uniformName + var replace = `texture2D( ${mapName}, ( ${uniformName} * vec3( vUv, 1. ) ).xy )` - level++ - prependUniforms += `uniform vec2 ${uniformNameScale};\n` - prependUniforms += `uniform vec2 ${uniformNameOffset};\n` - extraProps.push(mapName) - var foo = { - [`${mapName}Scale`]: { - get: function(){ return extraUniforms[uniformNameScale].value }, - set: function(val){ extraUniforms[uniformNameScale].value.copy(val) } - }, - [`${mapName}Offset`]: { - get: function(){ return extraUniforms[uniformNameOffset].value }, - set: function(val){ extraUniforms[uniformNameOffset].value.copy(val) } - } - } - Object.defineProperties( - _this, - foo - ) - - var replace = `texture2D( ${mapName}, vUv * ${uniformNameScale} + ${uniformNameOffset} )` return replaceMaps( replace ) } @@ -327,10 +320,47 @@ var material = materials[materialName] - for ( var map in validMaps ){ - if(material[map] === null) { - material[map] = texture + const extraUniforms = {} + material.userData.extraUniforms = extraUniforms + + const extraProps = [] + material.userData.extraProps = extraProps + + for ( var mapName in validMaps ){ + + if(material[mapName] === null) { + + material[mapName] = texture + material[`${mapName}Scale`] = new THREE.Vector2(1,1) + material[`${mapName}Offset`] = new THREE.Vector2() + material[`${mapName}Rotation`] = 0 + + var uniformName = `u_${mapName}Transform` + + var uniform = { value: new THREE.Matrix3() , name: mapName } + uniform.value.name = mapName + uniform.value.setUvTransform = setUvTransform.bind(uniform.value) + + extraUniforms[uniformName] = uniform + extraProps.push(mapName) + + let _mapName = mapName + let _uniformName = uniformName + + material[`${mapName}UpdateMatrix`] = function(){ + this.userData.extraUniforms[_uniformName].value.setUvTransform( + this[`${_mapName}Offset`].x, + this[`${_mapName}Offset`].y, + this[`${_mapName}Scale`].x, + this[`${_mapName}Scale`].y, + this[`${_mapName}Rotation`], + 0, + 0 + ) + }.bind(material) + } + } material.onBeforeCompile = onBeforeCompile.bind( material ) From aa72250835b82f7dde2e8375775a4b039cb719c6 Mon Sep 17 00:00:00 2001 From: Dusan Bosnjak Date: Wed, 30 May 2018 01:26:40 -0700 Subject: [PATCH 4/4] wrap inits so its less daunting --- examples/webgl_materials_extended_multiple_uvs.html | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/webgl_materials_extended_multiple_uvs.html b/examples/webgl_materials_extended_multiple_uvs.html index a6b11924d76a84..2286d50bf71892 100644 --- a/examples/webgl_materials_extended_multiple_uvs.html +++ b/examples/webgl_materials_extended_multiple_uvs.html @@ -62,7 +62,8 @@ var stats, gui, guiProps, guiMap; var guiData = { material: 'MeshStandard', map: 'map' } - init(); + initStuff() + initExtension() animate(); var guis = [] @@ -129,7 +130,7 @@ } - function init() { + function initStuff() { //share with other extended examples? // ----------------------------------------------------------------------------- @@ -189,7 +190,9 @@ window.addEventListener( 'resize', onWindowResize, false ); // ----------------------------------------------------------------------------- - + } + + function initExtension() { // some textures ----------------------------------------------------------------------