zoukankan      html  css  js  c++  java
  • WebGL编程笔记3:纹理图片texture

    HTML部分

    <script type="text/javascript" src="gl-matrix.js"></script>
    <canvas id="myCanvas" width="400" height="400" style="border: 1px solid red"></canvas>
    

    JavaScript部分

    以下两点若不注意texture2D有可能取不到值,一片黑色。

    • 老的显卡只支持图片尺寸为2的n次幂的纹理图片。
    • TEXTURE_MAG_FILTER和TEXTURE_MIN_FILTER参数需要制定。
    const vertex = `
        attribute vec3 v3Position;
        uniform   mat4 u_matrix;
        attribute vec2 inUv;
        varying   vec2 outUv;
        void main() {
           gl_Position = u_matrix * vec4(v3Position, 1.0);
           outUv = inUv;
        }
    `;
    // texture2D(u_texture, vec2(outUv.x, outUv.y));
    // texture2D(u_texture, outUv;
    // 从纹理texture中根据outUv坐标取色素rgba
    const fragment = `
        precision mediump   float;
        uniform   sampler2D u_texture;
        varying   vec2      outUv;
        void main() {
           gl_FragColor = texture2D(u_texture, vec2(outUv.x, outUv.y));
        }
    `;
    let canvas = document.getElementById('myCanvas');
    let webgl = canvas.getContext('webgl');
    const data_position = new Float32Array([
       // x       y     z      u       v
         30,     30,    0,    0.0,    0.0,
        330,     30,    0,    2.0,    0.0,
        330,    330,    0,    2.0,    2.0,
    
         30,     30,    0,    0.0,    0.0,
        330,    330,    0,    2.0,    2.0,
         30,    330,    0,    0.0,    2.0
    ]);
    const data_mat4 = glMatrix.mat4.ortho([], 0, canvas.clientWidth, canvas.clientHeight, 0, -10, 10);
    
    // 第一步:编译程序
    let program = createProgram(webgl, vertex, fragment);
    // 第二步:建立buffer
    let buffer_position = bindBufferWidthData(webgl, webgl.ARRAY_BUFFER, data_position);    // 创建数据缓冲区
    // 第三步:变量绑定
    let v3Position = bindVertexAttributePointer(webgl, program, "v3Position", 3, 20, 0);    // 绑定顶点输入变量v3Position的指针和取数方式
    let inUv       = bindVertexAttributePointer(webgl, program, "inUv", 2, 20, 12);         // 绑定顶点输入变量inUv坐标的指针和取数方式
    let matrix     = setUniformMatrix(webgl, program, 'u_matrix', data_mat4);               // 设置全局变量u_matrix的值
    
    let img = new Image();
    img.onload = ImageLoaded;
    img.src = '/static/imgs/sky.png';
    
    function ImageLoaded() {
        var texture = webgl.createTexture();         
        webgl.activeTexture(webgl.TEXTURE1);            // webgl有32个问题里图片,激活第二个纹理图片,一般使用第一个webgl.TEXTURE0    
        webgl.bindTexture(webgl.TEXTURE_2D, texture);   // 设置webgl的TEXTURE1为TEXTURE_2D,实例为创建的texture变量
    
        // 设置纹理图片的参数
        webgl.texImage2D(webgl.TEXTURE_2D, 0, webgl.RGBA, webgl.RGBA, webgl.UNSIGNED_BYTE, img); 
    
        // 图片的真实大小为256*256,实际绘制时的区域有可能大于图片实际尺寸,也有可能小于图片实际尺寸
        // 用于定义大于或小于真实尺寸时的图片算法,NEAREST效率高,LINEAR效率低但效果好,图片较小时看不出差别
        webgl.texParameteri(webgl.TEXTURE_2D,webgl.TEXTURE_MAG_FILTER,webgl.NEAREST);
        webgl.texParameteri(webgl.TEXTURE_2D,webgl.TEXTURE_MIN_FILTER,webgl.NEAREST);
        // 一般UV坐标或ST坐标处于0到1之间,有时也会超过1,超过1时的显示方式
        // gl.REPEAT 平铺
        // gl.MIRRORED_REPEAT 镜像(倒影)平铺
        // gl.CLAMP_TO_EDGE 使用边缘颜色填充
        webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_S, webgl.REPEAT);  // 横向
        webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_T, webgl.REPEAT);  // 纵向     
        
        let u_texture = webgl.getUniformLocation(program, "u_texture"); // 获取全局变量u_texture    
        webgl.uniform1i(u_texture, 1);                                  // 将全局变量赋值为webgl的第二个纹理图片
    
        clearCanvas(webgl);
        webgl.drawArrays(webgl.TRIANGLES, 0, 6);
    };

      

    函数

    /**
     * 编译shader源码并与webgl绑定,返回program对象
     * @param {*} webgl 
     * @param {*} vertex 
     * @param {*} fragment 
     */
    function createProgram(webgl, vertex, fragment) {
        // 创建程序
        let shader_vertex = webgl.createShader(webgl.VERTEX_SHADER);
        let shader_fragment = webgl.createShader(webgl.FRAGMENT_SHADER);
        webgl.shaderSource(shader_vertex, vertex);
        webgl.shaderSource(shader_fragment, fragment);
        // 编译源码
        webgl.compileShader(shader_vertex);
        webgl.compileShader(shader_fragment);
        if (webgl.getShaderParameter(shader_vertex, webgl.COMPILE_STATUS) === false) {
            console.error('Compile Shader Error: shader_vertex,' + webgl.getShaderInfoLog(shader_vertex));
        }
        if (webgl.getShaderParameter(shader_fragment, webgl.COMPILE_STATUS) === false) {
            console.error('Compile Shader Error: shader_fragment,' + webgl.getShaderInfoLog(shader_fragment));
        }
        // 创建执行程序
        let program = webgl.createProgram();
        webgl.attachShader(program, shader_vertex);
        webgl.attachShader(program, shader_fragment);
     
        // 连接context和program
        webgl.linkProgram(program);
        if(webgl.getProgramParameter(program, webgl.LINK_STATUS) === false) {
            console.error(webgl.getProgramInfoLog(program));
        }
        webgl.useProgram(program);
        return program;
    }
    /**
     * 向webgl添加buffer并传入data
     * @param {*} webgl 
     * @param {*} target 数据类型,gl.ARRAY_BUFFER
     * @param {*} data 
     */
    function bindBufferWidthData(webgl, target, data) {
        let buffer = webgl.createBuffer();
        webgl.bindBuffer(target, buffer);
        webgl.bufferData(target, data, webgl.STATIC_DRAW);  // 内存数据传入显存
    }
    /**
     * 建立JS变量和顶点输入变量的引用,返回JS变量
     * @param {*} webgl 
     * @param {*} program 
     * @param {String} varName Shader中的变量名
     * @param {Number} varSize 变量维度
     * @param {Number} stride 每段数据长度
     * @param {Number} offset 每段中的偏移量
     */
    function bindVertexAttributePointer(webgl, program, varName, varSize, stride, offset) {
        var pointer = webgl.getAttribLocation(program, varName);
        webgl.vertexAttribPointer(pointer, varSize, webgl.FLOAT, false, stride, offset);
        webgl.enableVertexAttribArray(pointer);
        return pointer;
    }
    
    /**
     * 向Shader传入mat4类型的全局变量
     * @param {*} webgl 
     * @param {*} program 
     * @param {String} varName 变量名称
     * @param {mat4} data 变量值
     */
    function setUniformMatrix(webgl, program, varName, data) {
        let matrix = webgl.getUniformLocation(program, 'u_matrix');
        webgl.uniformMatrix4fv(matrix, false, data);     // r g b a
        return matrix;
    }
    
    function clearCanvas(webgl) {
        webgl.clearColor(0.7, 0.7, 0.7, 1);
        webgl.clear(webgl.COLOR_BUFFER_BIT);
    }
    

      

  • 相关阅读:
    Fiddler显示响应时间
    WPF RichTextBox
    设计模式摘要
    sqlite insert时一直报constraint 约束
    try catch使用规则
    关于WPF的2000件事 06--WPF布局
    SmartAssembly 汉化说明
    GP80系列打印机驱动 V17下载地址
    记录 java 安卓 各类引用包报错处理方法 例如 android.support.v4.app.+ ,io.reactivex.+
    第一讲 新手如何学习HTTP协议之实践项目多开微信机器人
  • 原文地址:https://www.cnblogs.com/rainman/p/12593311.html
Copyright © 2011-2022 走看看