ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

WebGL编程笔记3:纹理图片texture

2020-03-29 17:01:50  阅读:258  来源: 互联网

标签:WebGL 编程 shader texture program let param webgl


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);
}

  

标签:WebGL,编程,shader,texture,program,let,param,webgl
来源: https://www.cnblogs.com/rainman/p/12593311.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有