提交 6fd0c88c 编写于 作者: W WestLangley

Added MeshMatcapMaterial

上级 84aa0008
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - materials - matcap</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
a {
color: #ffa;
font-weight: bold;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 0; // to not conflict with dat.gui
display:block;
}
</style>
</head>
<body>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl materials matcap<br />
Drag-and-drop alternate MatCap image files<br/>
</div>
<script src="../build/three.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/loaders/GLTFLoader.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
<script src="js/Detector.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var mesh, renderer, scene, camera;
var image;
var API = {
exposure : 1.0
}
init();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// tone mapping
renderer.toneMapping = THREE.LinearToneMapping;
renderer.toneMappingExposure = API.exposure;
renderer.gammaOutput = true;
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( - 10, 0, 23 );
// controls
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.minDistance = 10;
controls.maxDistance = 50;
controls.enablePan = false;
var loader = new THREE.TextureLoader();
var matcap = loader.load( 'textures/matcaps/matcap-porcelain-white.jpg', function( texture ) {
matcap.encoding = THREE.sRGBEncoding;
if ( mesh ) mesh.material.needsUpdate = true;
} );
// model
new THREE.GLTFLoader().load( 'models/gltf/Nefertiti/Nefertiti.glb', function ( gltf ) {
gltf.scene.traverse( function ( child ) {
if ( child.isMesh ) {
child.material = new THREE.MeshMatcapMaterial( {
matcap: matcap
} );
//
child.material.side = THREE.DoubleSide;
child.scale.multiplyScalar( 0.5 );
// recenter
new THREE.Box3().setFromObject( child ).getCenter( child.position ).multiplyScalar( - 1 );
mesh = child;
scene.add( mesh );
}
} );
render();
} );
// gui
var gui = new dat.GUI();
gui.add( API, 'exposure', 0, 2 )
.onChange( function() { renderer.toneMappingExposure = API.exposure; render(); } )
gui.domElement.style.webkitUserSelect = 'none';
// drag 'n drop
initDragAndDrop();
// corner div
var div = document.createElement( 'div' );
div.style.position = 'absolute';
div.style.top = '10px';
div.style.left = '10px';
document.body.appendChild( div );
image = document.createElement( 'img' );
image.style.width = '128px';
image.style.height = '128px';
image.style.display = 'block';
image.style.margin = '0 0 10px 0';
image.src = 'textures/matcaps/matcap-porcelain-white.jpg';
div.appendChild( image );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render();
}
function render() {
renderer.render( scene, camera );
}
//
// drag and drop anywhere in document
function imgCallback( event ) {
var matcap = mesh.material.matcap;
matcap.image = event.target;
matcap.needsUpdate = true;
render();
image.src = matcap.image.src; // corner div
}
function initDragAndDrop() {
document.addEventListener( 'dragover', function ( event ) {
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
}, false );
document.addEventListener( 'drop', function ( event ) {
event.preventDefault();
var reader = new FileReader();
reader.addEventListener( 'load', function ( event ) {
var img = new Image();
img.onload = imgCallback;
img.src = event.currentTarget.result;
}, false );
reader.readAsDataURL( event.dataTransfer.files[ 0 ] );
}, false );
}
</script>
</body>
</html>
......@@ -12,6 +12,7 @@ export { MeshLambertMaterial } from './MeshLambertMaterial.js';
export { MeshDepthMaterial } from './MeshDepthMaterial.js';
export { MeshDistanceMaterial } from './MeshDistanceMaterial.js';
export { MeshBasicMaterial } from './MeshBasicMaterial.js';
export { MeshMatcapMaterial } from './MeshMatcapMaterial.js';
export { LineDashedMaterial } from './LineDashedMaterial.js';
export { LineBasicMaterial } from './LineBasicMaterial.js';
export { Material } from './Material.js';
import { TangentSpaceNormalMap } from '../constants.js';
import { Material } from './Material.js';
import { Vector2 } from '../math/Vector2.js';
import { Color } from '../math/Color.js';
/**
* @author WestLangley / http://github.com/WestLangley
*
* parameters = {
* color: <hex>,
* opacity: <float>,
*
* matcap: new THREE.Texture( <Image> ),
*
* map: new THREE.Texture( <Image> ),
*
* bumpMap: new THREE.Texture( <Image> ),
* bumpScale: <float>,
*
* normalMap: new THREE.Texture( <Image> ),
* normalMapType: THREE.TangentSpaceNormalMap,
* normalScale: <Vector2>,
*
* displacementMap: new THREE.Texture( <Image> ),
* displacementScale: <float>,
* displacementBias: <float>,
*
* alphaMap: new THREE.Texture( <Image> ),
*
* skinning: <bool>,
* morphTargets: <bool>,
* morphNormals: <bool>
* }
*/
function MeshMatcapMaterial( parameters ) {
Material.call( this );
this.defines = { 'MATCAP': '' };
this.type = 'MeshMatcapMaterial';
this.color = new Color( 0xffffff ); // diffuse
this.matcap = null;
this.map = null;
this.bumpMap = null;
this.bumpScale = 1;
this.normalMap = null;
this.normalMapType = TangentSpaceNormalMap;
this.normalScale = new Vector2( 1, 1 );
this.displacementMap = null;
this.displacementScale = 1;
this.displacementBias = 0;
this.alphaMap = null;
this.skinning = false;
this.morphTargets = false;
this.morphNormals = false;
this.lights = false;
this.setValues( parameters );
// a matcap is required
if ( this.matcap === null ) {
var canvas = document.createElement( 'canvas' );
canvas.width = 1;
canvas.height = 1;
var context = canvas.getContext( '2d' );
context.fillStyle = '#fff';
context.fillRect( 0, 0, 1, 1 );
this.matcap = new THREE.CanvasTexture( canvas );
}
}
MeshMatcapMaterial.prototype = Object.create( Material.prototype );
MeshMatcapMaterial.prototype.constructor = MeshMatcapMaterial;
MeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;
MeshMatcapMaterial.prototype.copy = function ( source ) {
Material.prototype.copy.call( this, source );
this.defines = { 'MATCAP': '' };
this.color.copy( source.color );
this.matcap = source.map;
this.map = source.map;
this.bumpMap = source.bumpMap;
this.bumpScale = source.bumpScale;
this.normalMap = source.normalMap;
this.normalMapType = source.normalMapType;
this.normalScale.copy( source.normalScale );
this.displacementMap = source.displacementMap;
this.displacementScale = source.displacementScale;
this.displacementBias = source.displacementBias;
this.alphaMap = source.alphaMap;
this.skinning = source.skinning;
this.morphTargets = source.morphTargets;
this.morphNormals = source.morphNormals;
return this;
};
export { MeshMatcapMaterial };
......@@ -1723,6 +1723,7 @@ function WebGLRenderer( parameters ) {
if ( material.isShaderMaterial ||
material.isMeshPhongMaterial ||
material.isMeshStandardMaterial ||
// material.isMeshMatcapMaterial ||
material.envMap ) {
var uCamPos = p_uniforms.map.cameraPosition;
......@@ -1740,6 +1741,7 @@ function WebGLRenderer( parameters ) {
material.isMeshLambertMaterial ||
material.isMeshBasicMaterial ||
material.isMeshStandardMaterial ||
// material.isMeshMatcapMaterial ||
material.isShaderMaterial ||
material.skinning ) {
......@@ -1870,6 +1872,12 @@ function WebGLRenderer( parameters ) {
}
} else if ( material.isMeshMatcapMaterial ) {
refreshUniformsCommon( m_uniforms, material );
refreshUniformsMatcap( m_uniforms, material );
} else if ( material.isMeshDepthMaterial ) {
refreshUniformsCommon( m_uniforms, material );
......@@ -2281,6 +2289,40 @@ function WebGLRenderer( parameters ) {
}
function refreshUniformsMatcap( uniforms, material ) {
if ( material.matcap ) {
uniforms.matcap.value = material.matcap;
}
if ( material.bumpMap ) {
uniforms.bumpMap.value = material.bumpMap;
uniforms.bumpScale.value = material.bumpScale;
if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
}
if ( material.normalMap ) {
uniforms.normalMap.value = material.normalMap;
uniforms.normalScale.value.copy( material.normalScale );
if ( material.side === BackSide ) uniforms.normalScale.value.negate();
}
if ( material.displacementMap ) {
uniforms.displacementMap.value = material.displacementMap;
uniforms.displacementScale.value = material.displacementScale;
uniforms.displacementBias.value = material.displacementBias;
}
}
function refreshUniformsDepth( uniforms, material ) {
if ( material.displacementMap ) {
......
......@@ -102,6 +102,8 @@ import meshbasic_frag from './ShaderLib/meshbasic_frag.glsl';
import meshbasic_vert from './ShaderLib/meshbasic_vert.glsl';
import meshlambert_frag from './ShaderLib/meshlambert_frag.glsl';
import meshlambert_vert from './ShaderLib/meshlambert_vert.glsl';
import meshmatcap_frag from './ShaderLib/meshmatcap_frag.glsl';
import meshmatcap_vert from './ShaderLib/meshmatcap_vert.glsl';
import meshphong_frag from './ShaderLib/meshphong_frag.glsl';
import meshphong_vert from './ShaderLib/meshphong_vert.glsl';
import meshphysical_frag from './ShaderLib/meshphysical_frag.glsl';
......@@ -220,6 +222,8 @@ export var ShaderChunk = {
meshbasic_vert: meshbasic_vert,
meshlambert_frag: meshlambert_frag,
meshlambert_vert: meshlambert_vert,
meshmatcap_frag: meshmatcap_frag,
meshmatcap_vert: meshmatcap_vert,
meshphong_frag: meshphong_frag,
meshphong_vert: meshphong_vert,
meshphysical_frag: meshphysical_frag,
......
#if NUM_CLIPPING_PLANES > 0
#if ! defined( PHYSICAL ) && ! defined( PHONG )
#if ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )
varying vec3 vViewPosition;
#endif
......
#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )
#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )
varying vec3 vViewPosition;
#endif
#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )
#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )
vViewPosition = - mvPosition.xyz;
#endif
......@@ -104,6 +104,24 @@ var ShaderLib = {
},
matcap: {
uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.bumpmap,
UniformsLib.normalmap,
UniformsLib.displacementmap,
UniformsLib.fog,
{
matcap: { value: null }
}
] ),
vertexShader: ShaderChunk.meshmatcap_vert,
fragmentShader: ShaderChunk.meshmatcap_frag
},
points: {
uniforms: UniformsUtils.merge( [
......
#define MATCAP
uniform vec3 diffuse;
uniform float opacity;
uniform sampler2D matcap;
varying vec3 vViewPosition;
#ifndef FLAT_SHADED
varying vec3 vNormal;
#endif
#include <common>
#include <uv_pars_fragment>
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <fog_pars_fragment>
#include <bumpmap_pars_fragment>
#include <normalmap_pars_fragment>
#include <logdepthbuf_pars_fragment>
#include <clipping_planes_pars_fragment>
void main() {
#include <clipping_planes_fragment>
vec4 diffuseColor = vec4( diffuse, opacity );
#include <logdepthbuf_fragment>
#include <map_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
#include <normal_fragment_begin>
#include <normal_fragment_maps>
vec3 viewDir = normalize( vViewPosition );
vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );
vec3 y = cross( viewDir, x );
vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks
vec4 matcapColor = texture2D( matcap, uv );
matcapColor = matcapTexelToLinear( matcapColor );
vec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
#include <premultiplied_alpha_fragment>
#include <tonemapping_fragment>
#include <encodings_fragment>
#include <fog_fragment>
}
#define MATCAP
varying vec3 vViewPosition;
#ifndef FLAT_SHADED
varying vec3 vNormal;
#endif
#include <common>
#include <uv_pars_vertex>
#include <displacementmap_pars_vertex>
#include <fog_pars_vertex>
#include <morphtarget_pars_vertex>
#include <skinning_pars_vertex>
#include <logdepthbuf_pars_vertex>
#include <clipping_planes_pars_vertex>
void main() {
#include <uv_vertex>
#include <beginnormal_vertex>
#include <morphnormal_vertex>
#include <skinbase_vertex>
#include <skinnormal_vertex>
#include <defaultnormal_vertex>
#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED
vNormal = normalize( transformedNormal );
#endif
#include <begin_vertex>
#include <morphtarget_vertex>
#include <skinning_vertex>
#include <displacementmap_vertex>
#include <project_vertex>
#include <logdepthbuf_vertex>
#include <clipping_planes_vertex>
#include <fog_vertex>
vViewPosition = - mvPosition.xyz;
}
......@@ -491,8 +491,10 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
parameters.dithering ? '#define DITHERING' : '',
( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
( parameters.outputEncoding || parameters.mapEncoding || parameters.matcapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ?
ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
parameters.matcapEncoding ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',
......
......@@ -19,6 +19,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
MeshToonMaterial: 'phong',
MeshStandardMaterial: 'physical',
MeshPhysicalMaterial: 'physical',
MeshMatcapMaterial: 'matcap',
LineBasicMaterial: 'basic',
LineDashedMaterial: 'dashed',
PointsMaterial: 'points',
......@@ -27,7 +28,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
};
var parameterNames = [
"precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding",
"precision", "supportsVertexTextures", "map", "mapEncoding", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding",
"lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "displacementMap", "specularMap",
"roughnessMap", "metalnessMap", "gradientMap",
"alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
......@@ -139,6 +140,8 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
map: !! material.map,
mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
matcap: !! material.matcap,
matcapEncoding: getTextureEncodingFromMap( material.matcap, renderer.gammaInput ),
envMap: !! material.envMap,
envMapMode: material.envMap && material.envMap.mapping,
envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册