• 着色器应用贴图纹理并修改顶点实现“平地起丘陵”


    来张效果图先:

        var plane;
        function addpanel(){
            var axesHelper = new THREE.AxesHelper( 400 );
            scene.add( axesHelper );
            var geometry = new THREE.PlaneBufferGeometry( 200,200,400, 400);1
            var material = createMaterial("vertex-shader-2", "fragment-shader-2");
            material.uniforms.texture_grass={
                type:'t', 
                value:new THREE.TextureLoader().load("../texture/tile_aqua.png"),
            }
            material.uniforms.texture_grass.value.wrapS = THREE.RepeatWrapping;2
            material.uniforms.texture_grass.value.wrapT = THREE.RepeatWrapping;
            var displacement = new Float32Array(200000);3
            for(var i = 0; i < 200000; i++){
                displacement[i]=0;
            }
            //丘陵
            displacement = addmoutain(displacement,50,170,30,30);
            displacement = addmoutain(displacement,100,30,30,30);
            displacement = addmoutain(displacement,150,270,30,30);
            displacement = addmoutain(displacement,200,30,30,30);
            displacement = addmoutain(displacement,250,170,30,30);
            displacement = addmoutain(displacement,300,30,30,30);
            
            geometry.addAttribute('displacement', new THREE.BufferAttribute(displacement, 1));4
            plane = new THREE.Mesh( geometry, material );
            plane.rotation.x = -1;
            scene.add( plane );
        }

    1.利用PlaneBufferGeometry起了一块尺寸200X200的面板,后面的400,400是x轴y轴细分的三角形个数

    2.为着色器材质提供贴图纹理,并设置repeat(贴图尺寸必须为2的n次幂)

    3.因为plane被细分了(400 x 400,实际可能不是160000个顶点,就像两个三角形4个顶点,4个三角形却只有6个顶点,因为共用的问题)产生n个顶点,所以我们要提供相对应数量的数据供顶点使用;

    其实这些数据是后面要传给着色器,替换position.z的,addmoutain函数的作用是以第m个点为中心,周围radius半径内的点按一定规则升降(距离中心点越近,那么高度越高,即值越大)

    该函数如下:

        function addmoutain(arr,row,col,radius,height){
            var colstart = (col-radius+1)>0?(col-radius+1):1;
            var colend = (col+radius)>400?400:(col+radius);
            var rowstart = (row -radius + 1)>0?(row -radius + 1):1;
            var rowend = (row+radius)>400?400:(row+radius);
            for(var i = rowstart;i<=rowend;i++){
                for(var j = colstart;j<=colend;j++){
                    var distance = Math.sqrt(Math.pow((row-i),2) + Math.pow((col-j),2));
                    if(distance < radius){
                        var percent = (radius - distance)/radius;
                        var h = Math.sin(percent * Math.PI/2) * height/2;
                        arr[(i-1)*400+j-1] = h;
                    }
                }
            }
            return arr;
        }

    4.将写好的顶点z轴数据值传给geometry。

    下面来看两个着色器:

    vs:

    <script id="vertex-shader-2" type="x-shader/x-vertex">
        attribute float displacement;
        varying vec2 vUv;
        varying float pt;
        void main(){
            vUv = uv * 4.0; 
            pt = displacement;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position.xy,displacement, 1);
        }
    </script>

    通过uv * 4.0 实现贴图repeat,position.z值用displacement代替,pt(varying类型)用于后续fs计算透明度的依据

    fs:

    <script id="fragment-shader-2" type="x-shader/x-fragment">
        uniform sampler2D texture_grass;
        varying vec2 vUv;
        varying float pt;
    
        void main(){
            vec4 color = texture2D(texture_grass, vUv);
            float percent = 1.0;
            if(pt > 0.5){
                percent = pt / 15.0;
            }
            gl_FragColor = color * percent;
        }
    </script>

    因为最高的高度为15.0;所以pt/15.0实现的山丘的颜色透明过渡。

    这样,就写完了,后续考虑利用该种方法画一个围棋盘,敬请期待!

  • 相关阅读:
    编程基础——c 选择结构程序设计个人总结实例
    编程基础C——常量,变量,运算符个人总结
    编程基础C——格式化输入函数scanf的应用
    编程基础C——基本数据类型个人总结:
    django-base
    django-mvc
    OSI七层与TCP/IP五层网络架构详解
    tcp/ip三次握手及四次挥手
    网页浏览过程
    http协议
  • 原文地址:https://www.cnblogs.com/eco-just/p/11349480.html
Copyright © 2020-2023  润新知