Three.js相机控制不起作用& WebGL着色器

时间:2017-02-25 11:15:32

标签: three.js webgl shader

我从codepen找到了漂亮的水模拟,并在此处使用其他线程进行了修改(虽然找不到它)。

之前我曾经使用过三次.js,但现在我无法理解为什么相机定位/旋转/方面/等不起作用。无论我给相机的坐标或角度是什么,使用updateProjectionMatrix都没有任何反应,相机只停留在一个地方。

我评论了resize事件等,因为它们也没有做任何事情。

整个代码:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">


<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js"></script>


<style type="text/css">
    body {
    overflow: hidden;
    margin: 0;
    height: 100%;
    }
</style>

<title></title>


<script type='text/javascript'>//<![CDATA[
    window.onload=function(){
        // init camera, scene, renderer
        var scene, camera, renderer;
        scene = new THREE.Scene();
        var fov = 75,
        aspect = window.innerWidth / window.innerHeight;
        camera = new THREE.PerspectiveCamera(fov, aspect, 0.1, 1000);
        camera.position.z = 200;
        camera.rotate.z = 1.5707963268;

        camera.updateProjectionMatrix();

        renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(0xc4c4c4);
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);
        var clock = new THREE.Clock();

        var tuniform = {
            time: {
            type: 'f',
            value: 0.1
            },
            resolution: {
            type: 'v2',
            value: new THREE.Vector2()
            },
            mouse: {
            type: 'v4',
            value: new THREE.Vector2()
            }
        };

        // Mouse position in - 1 to 1
        renderer.domElement.addEventListener('mousedown', function(e) {
        //var canvas = renderer.domElement;
        //var rect = canvas.getBoundingClientRect();
        //tuniform.mouse.value.x = (e.clientX - rect.left) / window.innerWidth * 2 - 1;
        //tuniform.mouse.value.y = (e.clientY - rect.top) / window.innerHeight * -2 + 1; 


        });

        renderer.domElement.addEventListener('mouseup', function(e) {
            //var canvas = renderer.domElement;
            //var rect = canvas.getBoundingClientRect();
            //tuniform.mouse.value.z = (e.clientX - rect.left) / window.innerWidth * 2 - 1;
            //tuniform.mouse.value.w = (e.clientY - rect.top) / window.innerHeight * -2 + 1;
        });

        // resize canvas function
        window.addEventListener('resize',function() {
            //camera.aspect = window.innerWidth / window.innerHeight;
            //camera.updateProjectionMatrix();
            //renderer.setSize(window.innerWidth, window.innerHeight);
        });

        tuniform.resolution.value.x = window.innerWidth;
        tuniform.resolution.value.y = window.innerHeight;

        // Create Plane
        var material = new THREE.ShaderMaterial({
            uniforms: tuniform,
            vertexShader: document.getElementById('vertex-shader').textContent,
            fragmentShader: document.getElementById('fragment-shader').textContent
        });

        var mesh = new THREE.Mesh(
        new THREE.PlaneBufferGeometry(window.innerWidth, window.innerHeight, 40), material
    );

scene.add(mesh);


// draw animation
function render(time) {
    tuniform.time.value += clock.getDelta();
    requestAnimationFrame(render);
    renderer.render(scene, camera);
}
render();


}//]]> 

</script>


</head>

<body>
    <!-- THIS is OPENGL Shading language scripts -->
    <script id="vertex-shader" type="no-js">
        void main() {
        gl_Position = vec4( position, 1.0 );
        }
    </script>

<script id="fragment-shader" type="no-js">
    #ifdef GL_ES
    precision mediump float;
    #endif

    uniform float time;
    uniform vec2 mouse;
    uniform vec2 resolution;
    varying vec2 surfacePosition;

    const int NUM_STEPS = 8;
    const float PI      = 3.1415;
    const float EPSILON = 1e-3;
    float EPSILON_NRM   = 0.1 / resolution.x;

    // sea
    const int ITER_GEOMETRY = 3;
    const int ITER_FRAGMENT = 5;
    const float SEA_HEIGHT = 0.6;
    const float SEA_CHOPPY = 2.0;
    const float SEA_SPEED = 0.5;
    const float SEA_FREQ = 0.16;
    const vec3 SEA_BASE = vec3(0.1,0.19,0.22); //meren pohjaväri
    const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6);
    const float SKY_INTENSITY = 1.0;

    #define SEA_TIME time * SEA_SPEED

    // math
    mat4 fromEuler(vec3 ang) {
        vec2 a1 = vec2(sin(ang.x),cos(ang.x));
        vec2 a2 = vec2(sin(ang.y),cos(ang.y));
        vec2 a3 = vec2(sin(ang.z),cos(ang.z));
        mat4 m;
        m[0] = vec4(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x,0.0);
        m[1] = vec4(-a2.y*a1.x,a1.y*a2.y,a2.x,0.0);
        m[2] = vec4(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y,0.0);
        m[3] = vec4(0.0,0.0,0.0,1.0);
        return m;
    }
    vec3 rotate(vec3 v, mat4 m) {
        return vec3(dot(v,m[0].xyz),dot(v,m[1].xyz),dot(v,m[2].xyz));
    }

    float hash( vec2 p ) {
        float h = dot(p,vec2(127.1,311.7)); 
        return fract(sin(h)*43758.5453123);
    }

    float noise( in vec2 p ) {
        vec2 i = floor( p );
        vec2 f = fract( p );    
        vec2 u = f*f*(3.0-2.0*f);
    return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ), 
    hash( i + vec2(1.0,0.0) ), u.x),
    mix( hash( i + vec2(0.0,1.0) ), 
    hash( i + vec2(1.0,1.0) ), u.x), u.y);
    }


    // lighting
    float diffuse(vec3 n,vec3 l,float p) { return pow(dot(n,l) * 0.4 + 0.6,p); }
    float specular(vec3 n,vec3 l,vec3 e,float s) {    
        float nrm = (s + 8.0) / (3.1415 * 8.0);
        return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
    }

    // sky
    vec3 sky_color(vec3 e) {
        e.y = max(e.y,0.0);
        vec3 ret;
        ret.x = pow(1.0-e.y,2.0);
        ret.y = 1.0-e.y;
        ret.z = 0.6+(1.0-e.y)*0.4;
        return ret * SKY_INTENSITY;
    }

    // sea
    float sea_octave(vec2 uv, float choppy) {
        uv += noise(uv);        
        vec2 wv = 1.0-abs(sin(uv));
        vec2 swv = abs(cos(uv));    
        wv = mix(wv,swv,wv);
        return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
    }

    float map(vec3 p) {
        float freq = SEA_FREQ;
        float amp = SEA_HEIGHT;
        float choppy = SEA_CHOPPY;
        vec2 uv = p.xz; uv.x *= 0.75;
        mat2 m = mat2(1.6,1.2,-1.2,1.6);

        float d, h = 0.0;    
        for(int i = 0; i < ITER_GEOMETRY; i++) {        
        d = sea_octave((uv+SEA_TIME)*freq,choppy);
        d += sea_octave((uv-SEA_TIME)*freq,choppy);
        h += d * amp;        
        uv *= m; freq *= 1.9; amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
        }
        return p.y - h;
    }
    float map_detailed(vec3 p) {
        float freq = SEA_FREQ;
        float amp = SEA_HEIGHT;
        float choppy = SEA_CHOPPY;
        vec2 uv = p.xz; uv.x *= 0.75;
        mat2 m = mat2(1.6,1.2,-1.2,1.6);

        float d, h = 0.0;    
        for(int i = 0; i < ITER_FRAGMENT; i++) {        
        d = sea_octave((uv+SEA_TIME)*freq,choppy);
        d += sea_octave((uv-SEA_TIME)*freq,choppy);
        h += d * amp;        
        uv *= m; freq *= 1.9; amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
        }
        return p.y - h;
    }

    vec3 sea_color(in vec3 p, in vec3 n, in vec3 eye, in vec3 dist) {  
        float fresnel_o = 1.0 - max(dot(n,-eye),0.0);
        float fresnel = pow(fresnel_o,3.0) * 0.65;

        // reflection
        vec3 refl = sky_color(reflect(eye,n));

        // color
        vec3 ret = SEA_BASE;    
        ret = mix(ret,refl,fresnel);

        // wave peaks    
        float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
        ret += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;

        return ret;
    }

    // tracing
    vec3 getNormal(vec3 p, float eps) {
        vec3 n;
        n.y = map_detailed(p);    
        n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
        n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
        n.y = eps;
        return normalize(n);
    }
    float hftracing(vec3 ori, vec3 dir, out vec3 p) {  
        float tm = 0.0;
        float tx = 1000.0;    
        float hx = map(ori + dir * tx);
        if(hx > 0.0) return tx;   
        float hm = map(ori + dir * tm);    
        float tmid = 0.0;
        for(int i = 0; i < NUM_STEPS; i++) {
        tmid = mix(tm,tx, hm/(hm-hx));                   
        p = ori + dir * tmid;                   
        float hmid = map(p);
        if(hmid < 0.0) {
        tx = tmid;
        hx = hmid;
        } else {
        tm = tmid;
        hm = hmid;
        }
        }
        return tmid;
    }

    // main
    void main(void) {
        vec2 uv = gl_FragCoord.xy / resolution.xy;
        uv = 1.0 - uv * 2.0;
        uv.x *= resolution.x / resolution.y;   
        //uv = (surfacePosition+vec2(0., .5))*17. + 5E-3*(pow(length(surfacePosition+vec2(0. ,0.5)), -2.));
        uv.y *= -1.;
        //uv.y += -2.;

        // ray
        vec3 ang = vec3(0.0,0.003, pow(time, 0.6));
        ang = vec3(0.0,clamp(2.0-mouse.y*0.01,-0.3,PI),mouse.x*0.01);

        vec3 ori = vec3(0.0,3.5,time*.05);
        vec3 dir = normalize(vec3(uv.xy,-2.0));
        dir.z -= length(uv) * 0.15;
        //dir = rotate(normalize(dir),ang);

        // tracing
        vec3 p;
        float dens = hftracing(ori,dir,p);
        vec3 dist = p - ori;
        vec3 n = getNormal(p, dot(dist,dist)*EPSILON_NRM);

        // color
        vec3 color = sea_color(p,n,dir,dist);
        vec3 light = normalize(vec3(0.0,1.0,0.8));  
        color += vec3(diffuse(n,light,80.0) * SEA_WATER_COLOR) * 0.12; 
        color += vec3(specular(n,light,dir,60.0));  

        // post
        color = mix(sky_color(dir),color,pow(smoothstep(0.0,-0.05,dir.y),0.3)); 
        color = pow(color,vec3(0.75));
        gl_FragColor = vec4(color,1.0);
    }
</script>

<script>
    // tell the embed parent frame the height of the content
    if (window.parent && window.parent.parent){
        window.parent.parent.postMessage(["resultsFrame", {
        height: document.body.getBoundingClientRect().height,
        slug: "uz6yo2w3"
        }], "*")
    }
</script>

</body>

</html>

1 个答案:

答案 0 :(得分:1)

在这段代码中有很多尝试,我甚至不清楚你想要做什么,但我可以给出一些提示:

  1. camera.rotate更改为camera.rotation l。 30
  2. 您的鼠标事件已被评论。如果您想用鼠标旋转相机,则必须添加mousemove事件;
  3. 顺便说一下,l。 50您发送vec4但是将其加载为vec2 l。 126;
  4. 调整窗口大小时,您可能还希望将新分辨率更新为着色器;
  5. 升。 304,将相机原点的Z分量从vec3 ori = vec3(0.0, 3.5, time * 5.0);更改为vec3 ori = vec3(0.0, 3.5, time * 5.0);,以便您可以看到相机沿着海面移动;
  6. 升。 306,而不是dir = rotate(normalize(dir), ang);添加初始dir = normalize(dir) * fromEuler(ang);ang是相机的角度);
  7. 升。 149,将您的mat4 fromEuler(vec3 ang){...}更改为初始mat3 fromEuler(vec3 ang){...}功能;
  8. 升。 301,只需添加vec3 ang = vec3(0.0, 0.0, 0.0);并使用它。您可以在此功能中使用鼠标坐标,具体取决于您希望用户与相机进行交互的方式。