webGL学习随笔

 这是对threejs初步的一个理解

 

 

 

EleVR  elevr是基于webGL的原生API来实现的一个全景播放平台

首先elevr是根据绘制适口来进行双屏VR渲染的web

 

if (eye === 0) { // left eye
    webGL.gl.viewport(0, 0, canvas.width / 2, canvas.height);
} else { // right eye
    webGL.gl.viewport(canvas.width / 2, 0, canvas.width / 2, canvas.height);
}编程

 

由于自己对webGLAPI不熟悉,因此改写是存在很大难度的canvas

经过层层样式的修改,经过用localstorage本地存储的方式写入一个变量值,每次点击去修改其存储的值,而后根据存入值的一个状态来决定走哪一个绘制vierport,最后reload页面,基本实现单双屏切换的状态,跨域

可是用户体验确定不是很乐观,稍后会对webGL进入深层次的一个学习,暂时用此方法替代单双屏切换的一个状态浏览器

具体实现代码cookie

var btn = document.getElementById("btn");//获取点击按钮的dom元素
btn.onclick = function(){//注册一个点击事件
    if (window.localStorage) {//判断浏览器是否支持localstorage
        if(localStorage.VR && localStorage.VR == "on"){dom

//判断当前存入的VR是否有值或者值是什么
            localStorage.VR = "off";
        }else{
            localStorage.VR = "on";
        }
    } else {//若是浏览器不支持localstorage,不支持当前存入的一个切换
        alert("sorry,换个浏览器试试")
       //setcookie
    }

    location.reload();//reload页面
};编程语言

 

绘制vierport的代码ide

  if (window.localStorage) {//判断浏览器是否支持localstorage
      if (localStorage && localStorage.VR == "on") {
          if (eye === 0) { // left eye
              webGL.gl.viewport(0, 0, canvas.width / 2, canvas.height);
          } else { // right eye
              webGL.gl.viewport(canvas.width / 2, 0, canvas.width / 2, canvas.height);
          }
      }
      else {
          if (eye === 0) { // left eye
              webGL.gl.viewport(0, 0, canvas.width, canvas.height);
          } else { // right eye
              webGL.gl.viewport(0, 0, canvas.width, canvas.height);
          }
      }
  }else{
      if (eye === 0) { // left eye
          webGL.gl.viewport(0, 0, canvas.width / 2, canvas.height);
      } else { // right eye
          webGL.gl.viewport(canvas.width / 2, 0, canvas.width / 2, canvas.height);
      }
  }
    // Draw
    webGL.gl.bindBuffer(webGL.gl.ELEMENT_ARRAY_BUFFER, verticesIndexBuffer);
    webGL.gl.drawElements(webGL.gl.TRIANGLES, 6, webGL.gl.UNSIGNED_SHORT, 0);
},函数

 

 

Threejs

Threejs的具体切换原理是基于camare来切换绘制渲染,

 

 

 

 

webGL

webGL的纹理对象

纹理映射的四个步骤:

 1.准备好映射的图像   能够是任意图片png  jpg

 2.为几何图形配置纹理映射方式

   1》纹理坐标

     

纹理坐标值与图像尺寸无关,其坐标值是通用的

 

 

 

 

 3.加载纹理图像,对其进行一些配置,方便在webGL中使用它

 4.在片元着色器中将相应的纹素从纹理中抽取出来,并将纹素的颜色赋给片元

 

var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'attribute vec2 a_TexCoord;\n' +
  'varying vec2 v_TexCoord;\n' +
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '  v_TexCoord = a_TexCoord;\n' +
  '}\n';

// Fragment shader program
var FSHADER_SOURCE =
  '#ifdef GL_ES\n' +
  'precision mediump float;\n' +
  '#endif\n' +
  'uniform sampler2D u_Sampler;\n' +
  'varying vec2 v_TexCoord;\n' +
  'void main() {\n' +
  '  gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n' +
  '}\n';

function main() {   //主入口函数
  // Retrieve <canvas> element
  var canvas = document.getElementById('webgl');

  // Get the rendering context for WebGL
  var gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }

  // Initialize shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  // S设置顶点信息
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the vertex information');
    return;
  }

  // Specify the color for clearing <canvas>
  gl.clearColor(0.0, 0.0, 0.0, 1.0);

  // 配置纹理
  if (!initTextures(gl, n)) {
    console.log('Failed to intialize the texture.');
    return;
  }
}

function initVertexBuffers(gl) {
  var verticesTexCoords = new Float32Array([
    // 顶点坐标  纹理坐标
    -0.5,  0.5,   0.0, 1.0,
    -0.5, -0.5,   0.0, 0.0,
     0.5,  0.5,   1.0, 1.0,
     0.5, -0.5,   1.0, 0.0,
  ]);
  var n = 4; // 顶点的数量
  // 建立缓冲区对象
  var vertexTexCoordBuffer = gl.createBuffer();
  if (!vertexTexCoordBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }

  // 将顶点坐标和纹理坐标写入缓冲区对象
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);

  var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
  //Get the storage location of a_Position, assign and enable buffer
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
  gl.enableVertexAttribArray(a_Position);  // Enable the assignment of the buffer object

  // 将纹理坐标分配给a_TexCoord 而且开启它
  var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
  if (a_TexCoord < 0) {
    console.log('Failed to get the storage location of a_TexCoord');
    return -1;
  }
  // Assign the buffer object to a_TexCoord variable
  gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
  gl.enableVertexAttribArray(a_TexCoord);  // Enable the assignment of the buffer object

  return n;
}

function initTextures(gl, n) {
  var texture = gl.createTexture();   // 建立纹理对象
  if (!texture) {
    console.log('Failed to create the texture object');
    return false;
  }

  // 获取u_Sampler的存储位置
  var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
  if (!u_Sampler) {
    console.log('Failed to get the storage location of u_Sampler');
    return false;
  }
  var image = new Image();  // 建立一个image对象
  if (!image) {
    console.log('Failed to create the image object');
    return false;
  }
  // 注册图像加载事件的相应函数
  image.onload = function(){ loadTexture(gl, n, texture, u_Sampler, image); };
  // 把路径添加到src让浏览器加载
  image.src = '../resources/sky.jpg';

  return true;
}

function loadTexture(gl, n, texture, u_Sampler, image) {
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // 对纹理图像进行Y轴反转,是由于webGL的坐标跟图像的y轴正好是相反的,因此须要y轴反转,或者在着色器中进行纹理的t轴反转


  // 开启0号纹理单元
  gl.activeTexture(gl.TEXTURE0);


  // 向target绑定纹理对象
  gl.bindTexture(gl.TEXTURE_2D, texture);

  // 配置纹理参数
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  // 配置纹理图像
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
  
  // 将0号纹理传递给着色器
  gl.uniform1i(u_Sampler, 0);
  
  gl.clear(gl.COLOR_BUFFER_BIT);   // Clear <canvas>

  gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // D绘制矩形
}

 

 

1.顶点着色器中接收顶点的纹理坐标,光栅化后传递给片元着色器

2.片元着色器根据片元的纹理坐标,从纹理图像中抽取纹素颜色,赋给当前片元

3.设置顶点的纹理坐标initVertexBuffers()

4.准备待加载的纹理图像,令浏览器读取它initTextures()

5.监听纹理图像的加载事件,一旦加载完成,就在webGL系统中使用纹理loadTexture()

 

Gl_TEXTURE0-------GL_TEXTURE7八个纹理单元都与gl_TEXTURE_2D相关联

 

Gl_deleteTexture  删除一个纹理对象

LoadTexture(gl,n,texture,u_Sampler,image),loadtexture有五个参数,第一个参数为绘制上下文,第二个为绘制的顶点的个数,第三个为以前建立的纹理对象,第四个是从uniform中取得的变量u_Sampler的存储位置,第五个是咱们须要渲染的图片

webGL不容许跨域的纹理图像

从浏览器加载图像到loadTexture函数调用图像

 

 

Gl.pixelStorei()方法的规范

 

Gl.activeTexture(gl.texTure0)激活纹理单元,参数为八个纹理单元

 

在对纹理对象进行操做以前,还须要绑定纹理单元,跟绑定缓冲区对象很相似

开启纹理对象并绑定纹理到target

Gl.bindTexTure(gl.texTure2D,texTure);绑定二维纹理对象

Gl.bindTexTure(gl.texTure_CUBE_MAP,texTure);绑定立方体纹理对象

 

 

注意:在webGL中没办法直接操控纹理对象,只能把纹理对象绑定到纹理单元上,而后经过操控纹理单元来操控纹理对象;

配置纹理对象的参数gl.texParameteri()

 

经过paname能够指定四个纹理参数

放大方法:gl.texTure_MAG_FILTER 当纹理的绘制自己比纹理更大时

缩小方法:gl.texTure_MIN_FILTER  当绘制的纹理比纹理更小时

水平填充方法:gl.texTure_wrap_s

垂直填充方法:gl.texTure_wrap_t

其图示以下:

 

 

 

 

将纹理图像分配给纹理对象gl.texImage2D()

 

 

若是为png格式的图片就用gl.rgba  jpg之类的就用gl.rgb

 

 

GLSL ES 编写着色器的编程语言

必须有且仅有一个main函数作为主函数

Void声明一个函数没有返回值

支持整型数和浮点数,支持布尔类型,不支持字符串

变量命名规范和js类似,如下是关键字

 

GLSL ES 是一种强类型语言,必须声明数据类型

float()将整形转换为浮点数

Int()转换为整型数

Booln()转换为布尔值,0false

 

Mat4矩阵函数

Vec4

 

Attribute  顶点着色器里声明的全局变量,

Varying   从顶点着色器向片元着色器传输数据,也是一个全局变量

Uniform

Const  表示声明一个变量且这个变量是不可改变的,而且不能从新赋值,不然会致使报错

 

 

 

片元着色器中要对float类型的精度作限定,否则就会编译报错

 

指令必须在最顶部

 

SetlokAt

 

GLSL 变量的使用

var VSHADER_SOURCE =  'attribute vec4 a_Position;\n' +  'void main() {\n' +  '  gl_Position = a_Position;\n' +  '  gl_PointSize = 10.0;\n' +  '}\n';

首先看顶点着色器,咱们声明了a_Position变量,接下来咱们经过下面的方法进行赋值。

var a_Position = gl.getAttribLocation(gl.program, 'a_Position');

gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);

gl.enableVertexAttribArray(a_Position);

getAttribLocationprogram, name

js中,咱们首先经过getAttribLocation()获取到变量 a_Position 在渲染器中的地址。 该方法接收两个变量

  • program project对象
  • name 变量名称

接下来咱们经过vertexAttribPointer()方法,指定了如何处理渲染器中的值。

vertexAttribPointer(index, size, type, normalized, stride, offset);

比较复杂的一个方法

  • index 绑定在gl.ARRAY_BUFFER中的目标索引,比较难理解,可是一般状况下咱们能够经过getAttribLocation来获取这个值。
  • size 每一个属性的长度 [1234(default)]
  • type 类型 指定数据类型 咱们有两个选择,[gl.FLOAT (default)|gl.FIXED]
  • normalized 是否初始化传入的数据 [gl.FALSE|gl.TRUE]
  • stride 每组数据的个数,[0-255]
  • offset 这一组中的数据起始位置(从0开始)

接下来启用 enableVertexAttribArray()

enableVertexAttribArray(index);

  • index vertexAttribPointer中的index

开启深度检测肯定是否将其画出来,就是所谓的物体遮挡面是否显示 gl.enable(gl.DEPTH_TEST)开启隐藏面消除功能,固然还有多边形偏移的功能

在绘制以前,清除深度缓冲区gl.clear(gl_DEPTH_BUFFER_BIT);一般时绘制每一帧以前

深度缓冲区通常是用来存储深度信息的,深度通常都是Z轴方向,因此又称Z缓冲区

Gl.desable()关闭某种功能

 

A_Normal   

建立着色器对象

 

着色器对象管理一个顶点着色器或一个片元着色器,每个着色器都有一个着色器对象

程序对象是管理着色器对象的容器,webGL中,一个程序对象必须包含一个顶点着色器和一个片元着色器

 

 

程序对象一旦被建立,就须要附上两个着色器对象

相关文章
相关标签/搜索