卜若的代码笔记-webgl系列-第十九章:glsl探索(七)$关于VertexShader向FragmentShader传递的uv的探索和思考$

1 使用立方体去探索它的uv是一个很复杂的过程,及其变态,所以为了解决这个问题,我们需要去简化它,最简单的方法就是通过三角面去探索这个问题。

1.1 以下是一个封装好的用于三角面的函数

var geometryCache = new Array();

function geometryCachePush(vector3) {

    geometryCache.push(vector3);
}
function createMeshWithoutMaterial() {


    var geometry = new THREE.Geometry();
    var material = null;

    for (var i in geometryCache)
    {
        console.info(geometryCache[i]);
        geometry.vertices.push(new THREE.Vector3(geometryCache[i].x,geometryCache[i].y,geometryCache[i].z));
    }
    var normal = new THREE.Vector3( 0, 0, 1 ); //三角面法向量,x,y,z定义z轴为法向量


    for (var i = 0;i<geometryCache.length - 2;i++)
    {


        geometry.faces.push( new THREE.Face3( 0, 1+i, 2+i, normal) ); //三角面添加到几何体
    }

    var msh = new THREE.Mesh(geometry,material );
    addObject(msh);
    geometryCache.length = 0;
    return msh;
}

1.2 使用

其实怎么使用这并不重要,实现的过程仁者见仁智者见智,我们主要去探索这里面shader的变化。

创建的Shader:

    <script id="fragment_shader" type="x-shader/x-fragment">
        uniform float time;
        uniform float width;
        uniform float height;
        varying vec3 suv;
        float dynamic;
        void main( void ) {

          gl_FragColor = vec4(0.0,1.0,0.0, 1.0 );


        }

    </script>
    <script id="vertexShader" type="x-shader/x-vertex">
        varying vec3 suv;
        void main()
        {
        suv = position;
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        gl_Position = projectionMatrix * mvPosition;

        }

    </script>

先来看一下效果:

1.3 现在我们来思考我们在这一章中要讨论的问题:UV的传递:

那么,什么是UV

这是一段来自百度百科的解释:

UV"这里是指u,v纹理贴图坐标的简称(它和空间模型的X, Y, Z轴是类似的). 它定义了图片上每个点的位置的信息.

ok,所以,我们完全可以认为UV就是顶点坐标!!,而且这个顶点坐标是各个片元的顶点坐标,我是什么意思呢,意思就是,uv只有在三角面这个mesh的单元里面才有意义。

如果你说三个顶点head,leg,arm,那你觉得这三个顶点是uv吗?显然不是的,学过离散数学,我们会知道,在计算机里面点是离散的,线,其实本质上是由离散的点构成的,这就意味着面,也是由离散的面构成,只是让人感觉更不可思议的是:

就算是最小的单元,三角面本身,里面的点也是足够密集的,密集到,你可以当他成为一个面,而不会将它当做是一个镂空的纱窗。

这一段话实在是太抽象了,接下来我会做一个实验,让你们理解下这段话想要表达的思想。

我绘制的这个四边形,其实由两个三角面组成。

也就是说,它由两个基本元素Triangle组成,那么uv在这里面已经有足够的意义,如果我要用三个点去描述一个人的纹理的位置信息...你就会看到一个三角形,你看不见它穿的衣服,看不到它的脸,就是一个妥妥的丑逼,我们称之为三角星人。

当然,其实这不重要。

对于这个四边形,我们让它分配的UV是什么呢?

如下:

这个就是它的uv了,我们通常见到的...嗯uv坐标是-1~1之间,那么只需要进行归一化就行,这本质上其实非常简单。

 接下来,我将要做一个更加具有实际意义,也更加让人深入理解什么叫uv的骚操作。

我们知道FragmentShader下面的函数:gl_FragColor是一个逐顶点上色的过程。

那么,我现在,在我这个四边形的基础上,对它进行上色

上色的代码如下:

上色结果: 

这个典型的逐顶点的操作。

我们所看到的一张图像里面,其实有很多像素,比如一张512*512*3的图像,那么对于这张图像每一个像素上色的过程就是gl_FragColor要干的事情。

这是一种uv分配的方式,但是,事实上呢,glsl在设计的时候,它其实是提供了你一个自定义uv的接口,因为,通常情况下我们会有非常奇葩的需求,比如,我们要让贴图倒着来,如果直接在FragmentShader里面操作,这样会...嗯,反正我觉得可以,但是,这其实不重要,主要是uv还有另外一种方式,那就是直接定义顶点的uv

比如这种做法:

geometry.vertices[0].uv = new THREE.Vector2(0,0);

这样,其实就可以直接使用Varying将uv传递个FragmentVertex:

 如果,我要直接分配四个顶点的uv,用这种方式确实要比那种要爽很多:

就这样....哎

下一章我们讲什么呢?我们懂了uv,那么是不是应该尝试将一张彩色图像匹配到这个显示块里面呢?

发布了202 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_37080133/article/details/101021964
今日推荐