我正在尝试理解并致力于在three.js中实现毛发,我在http://oos.moxiecode.com/js_webgl/fur/找到了示例。我试图这样做,作为一个例子来了解并理解代码。
模型加载,但现在问题是毛皮纹理没有加载,我添加了控制台上出现的错误,这些错误都链接到three.min.js。我已经加载了演示中使用的three.min.js r58版本和我当前的版本,错误/警告不会随着我使用的任何一个而改变。
这是模型,它加载但没有毛发纹理加载:
代码:
<!doctype html>
<html lang="en">
<head>
<title>three.js fur example 1</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" type="text/css" href="style_no_stats.css">
<style type="text/css">
body {
background:#000000;
}
</style>
</head>
<body>
<script src="three.min.js"></script>
<script src="info.js"></script>
<script type="x-shader/x-vertex" id="vertexshader">
uniform float offset;
uniform float globalTime;
uniform vec3 gravity;
varying vec2 vUv;
varying vec3 vNormal;
const float spacing = 12.0;
void main()
{
vec3 displacement = vec3(0.0,0.0,0.0);
vec3 forceDirection = vec3(0.0,0.0,0.0);
// "wind"
forceDirection.x = sin(globalTime+position.x*0.05) * 0.2;
forceDirection.y = cos(globalTime*0.7+position.y*0.04) * 0.2;
forceDirection.z = sin(globalTime*0.7+position.y*0.04) * 0.2;
// "gravity"
displacement = gravity + forceDirection;
float displacementFactor = pow(offset, 3.0);
vec3 aNormal = normal;
aNormal.xyz += displacement*displacementFactor;
// move outwards depending on offset(layer) and normal+force+gravity
vec3 animated = vec3( position.x, position.y, position.z )+(normalize(aNormal)*offset*spacing);
vNormal = normalize(normal*aNormal);
vUv = uv*20.0;
vec4 mvPosition = modelViewMatrix * vec4( animated, 1.0 );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform sampler2D hairMap;
uniform sampler2D colorMap;
uniform vec3 color;
uniform float offset;
varying vec3 vNormal;
varying vec2 vUv;
void main()
{
vec4 hairColor = texture2D(hairMap, vec2(vUv.s, vUv.t));
vec4 col = texture2D(colorMap, vec2(vUv.s*0.2, vUv.t*0.2));
// discard no hairs + above the max length
if (hairColor.a <= 0.0 || hairColor.g < offset) {
discard;
}
// darker towards bottom of the hair
float shadow = mix(0.0,hairColor.b*1.2,offset);
// light
vec3 light = vec3(0.1,1.0,0.3);
float d = pow(max(0.25,dot(vNormal.xyz, light))*2.75, 1.4);
gl_FragColor = vec4(color*col.xyz*d*shadow, 1.1-offset);
}
</script>
<script>
var container;
var camera, scene, renderer;
var has_gl = false;
var delta;
var time;
var oldTime;
var shaderTime = 0;
var meshes = [];
var overlay;
var texture;
var color;
var vignette;
var mouse = new THREE.Vector2(-0.5,0.5);
var gravity = new THREE.Vector3(0,-0.75,0);
var mouseObj = {x:0, y: 0, vx: 0, vy:0};
var touchDevice = ( ('ontouchstart' in document) || (navigator.userAgent.match(/ipad|iphone|android/i) != null) );
var scaleRatio = 1;
if (touchDevice) scaleRatio = 2;
document.addEventListener( 'mousemove', onMouseMove, false );
document.addEventListener( 'touchmove', onTouchMove, false );
var loadedItems = 0;
function checkLoading () {
++loadedItems;
if (loadedItems < 3) return;
animate();
}
init();
function init()
{
container = document.createElement( 'div' );
document.body.appendChild( container );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 150;
camera.lookAt(scene.position);
scene.add( camera );
// diffuse color
color = THREE.ImageUtils.loadTexture( "11133-v4.jpg", undefined, checkLoading);
color.wrapS = color.wrapT = THREE.RepeatWrapping;
// hair texture
texture = new THREE.Texture( generateTexture() );
texture.needsUpdate = true;
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
vignette = THREE.ImageUtils.loadTexture( "VignetteWithDirt_alpha_sq.png", undefined, checkLoading);
// model
loader = new THREE.JSONLoader();
loader.load( "suzanne.js", meshLoaded );
var overlayMaterial = new THREE.SpriteMaterial( { map: vignette, useScreenCoordinates: true, opacity: 0.4 } );
overlay = new THREE.Sprite( overlayMaterial );
overlay.scale.set( window.innerWidth/scaleRatio, window.innerHeight/scaleRatio , 1 );
overlay.position.set((window.innerWidth/scaleRatio)/2, (window.innerHeight/scaleRatio)/2 , 0);
camera.add(overlay);
try
{
// renderer
renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setSize( window.innerWidth/scaleRatio, window.innerHeight/scaleRatio );
renderer.setClearColor(0x444444);
texture.anisotropy = renderer.getMaxAnisotropy();
if (scaleRatio > 1)
{
renderer.domElement.style.position = "absolute";
renderer.domElement.style.top = "0px";
renderer.domElement.style.left = "0px";
renderer.domElement.style.webkitTransform = "scale3d("+scaleRatio+", "+scaleRatio+", 1)";
renderer.domElement.style.webkitTransformOrigin = "0 0 0";
renderer.domElement.style.transform = "scale3d("+scaleRatio+", "+scaleRatio+", 1)";
renderer.domElement.style.transformOrigin = "0 0 0";
}
window.addEventListener( 'resize', onWindowResize, false );
container.appendChild( renderer.domElement );
container.style.cursor = "url(cursor.png),pointer";
has_gl = true;
}
catch (e)
{
// need webgl
document.getElementById('info').innerHTML = "<P><BR><B>Note.</B> You need a modern browser that supports WebGL for this to run the way it is intended.<BR>For example. <a href='http://www.google.com/landing/chrome/beta/' target='_blank'>Google Chrome 9+</a> or <a href='http://www.mozilla.com/firefox/beta/' target='_blank'>Firefox 4+</a>.<BR><BR>If you are already using one of those browsers and still see this message, it's possible that you<BR>have old blacklisted GPU drivers. Try updating the drivers for your graphic card.<BR>Or try to set a '--ignore-gpu-blacklist' switch for the browser.</P><CENTER><BR><img src='../general/WebGL_logo.png' border='0'></CENTER>";
document.getElementById('info').style.display = "block";
return;
}
}
function onWindowResize ( event )
{
var w = window.innerWidth;
var h = window.innerHeight;
renderer.setSize( w/scaleRatio, h/scaleRatio );
camera.aspect = w / h;
camera.updateProjectionMatrix();
if (overlay)
{
overlay.scale.set( w/scaleRatio, h/scaleRatio, 1 );
overlay.position.set((w/scaleRatio)/2, (h/scaleRatio)/2 , 0);
}
}
function onMouseMove ( event )
{
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function onTouchMove ( event )
{
event.preventDefault();
mouse.x = ( event.touches[0].clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.touches[0].clientY / window.innerHeight ) * 2 + 1;
}
function meshLoaded( geometry )
{
// scale it up
var size = 60;
geometry.applyMatrix( new THREE.Matrix4().scale( new THREE.Vector3( size, size, size ) ) );
// number of "shells" / layers
var shells = 60;
if (touchDevice) shells = 45;
for (var i = 0; i < shells; i++)
{
var attributes = {};
var uniforms =
{
color: { type: "c", value: new THREE.Color( 0xffffff ) },
hairMap: { type: "t", value: texture },
colorMap: { type: "t", value: color },
offset: { type: "f", value: i/shells },
globalTime: { type: "f", value: shaderTime },
gravity: { type: "v3", value: gravity },
};
var material = new THREE.ShaderMaterial(
{
uniforms: uniforms,
attributes: attributes,
vertexShader: document.getElementById( "vertexshader" ).textContent,
fragmentShader: document.getElementById( "fragmentshader" ).textContent,
transparent: true,
});
var mesh = new THREE.Mesh(geometry, material);
mesh.matrixAutoUpdate = false;
mesh.frustumCulled = false;
scene.add(mesh);
meshes.push(mesh);
}
checkLoading();
}
function generateTexture()
{
var canvas = document.createElement( 'canvas' );
canvas.width = 256;
canvas.height = 256;
var context = canvas.getContext( '2d' );
for ( var i = 0; i < 20000; ++i ) {
// r = hair 1/0
// g = length
// b = darkness
context.fillStyle = "rgba(255," + Math.floor( Math.random() * 255 ) + ","+ Math.floor( Math.random() * 255 ) +",1)";
context.fillRect( ( Math.random() * canvas.width ), ( Math.random() * canvas.height ), 2, 2 );
}
return canvas;
}
function animate()
{
requestAnimationFrame( animate );
render();
}
function render()
{
time = Date.now();
delta = time - oldTime;
oldTime = time;
if (isNaN(delta) || delta > 1000 || delta == 0 )
{
delta = 1000/60;
}
var optimalDivider = delta/16;
var smoothing = Math.max(4, (20/optimalDivider) )
// fake some gravity according to mouse movement
var xf = (mouse.x - mouseObj.x)/(smoothing*5);
var yf = (mouse.y - mouseObj.y)/(smoothing*5);
mouseObj.vx += xf
mouseObj.vy += yf;
mouseObj.vx *= 0.96;
mouseObj.vy *= 0.94;
mouseObj.x += mouseObj.vx;
mouseObj.y += mouseObj.vy;
gravity.x = -(mouse.x-mouseObj.x)*2;
var dif = Math.sin(mouse.x)*150 - camera.position.x;
gravity.y = -0.75 + (Math.abs(dif)/150) - (mouse.y-mouseObj.y)*2;
camera.position.x += (Math.sin(mouse.x)*150 - camera.position.x)/smoothing;
camera.position.z += (Math.cos(mouse.x)*150 - camera.position.z)/smoothing;
camera.position.y += (Math.sin(mouse.y)*150 - camera.position.y)/smoothing;
camera.lookAt(scene.position);
shaderTime += delta*0.005;
for (var i = 0; i < meshes.length; i++)
{
meshes[i].material.uniforms.globalTime.value = shaderTime;
}
if (has_gl) {
renderer.render( scene, camera );
}
}
</script>
</body>
</html>
控制台中的错误是:
three.min.js:835 THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.
loadTexture @ three.min.js:835
three.min.js:419 THREE.SpriteMaterial: 'useScreenCoordinates' is not a property of this material.
setValues @ three.min.js:419
three.min.js:32 THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.
setValues @ three.min.js:419
three.min.js:32 THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.
由于我复制的代码不确定我做错了什么,我有所有.png和.jpg文件,我在本地服务器上有所有的javascript文件。