webgl学习笔记(阴影)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

个人学习webgl笔记。本文通过对webgl进行简单封装,并实现阴影效果,可以更直观展示webgl的代码流程。主要为mesh.js,shadow.js这两个的封装。


一、mesh.js

参考three.js,这里可以添加必要元素

//首先引入两个工具
import cuonUtils from '../js/cuon-utils'
import cuonMatrix from '../js/cuon-matrix'

class Mesh{
    //gl是一定需要的
    //attributeData包含顶点,法向量,uv,索引数据
    //vs顶点着色器
    //fs片元着色器
    //baseTextureList未处理的纹理数据

    constructor(gl,name='',attributeData={},vs,fs,baseTextureList=[],opertions={}){
    
        this.gl = gl
    
    this.modelMatrix = new cuonMatrix.Matrix4();//M矩阵
    this.transposeInverseModelMatrix = new cuonMatrix.Matrix4();//M逆转置矩阵

    //世界空间位置
    this.position = {
      x:0,
      y:0,
      z:0,
      set:(x,y,z)=>{
        this.position.x = x
        this.position.y = y
        this.position.z = z
        this.modelMatrix.elements[12] = x
        this.modelMatrix.elements[13] = y
        this.modelMatrix.elements[14] = z

        this.transposeInverseModelMatrix = new cuonMatrix.Matrix4(this.modelMatrix)
        this.transposeInverseModelMatrix.invert().transpose()
      }
    }
    //缩放
    this.scale = {
      x:1,
      y:1,
      z:1,
      set:(x,y,z)=>{
        this.scale.x = x
        this.scale.y = y
        this.scale.z = z
        this.modelMatrix.scale(x,y,z)
        this.transposeInverseModelMatrix = new cuonMatrix.Matrix4(this.modelMatrix)
        this.transposeInverseModelMatrix.invert().transpose()
      }
    }

    //处理后的 顶点,法向量,uv,索引数据
    this.geometry = {}

    //着色器对象(这是默认的着色器)
    this.material = {
      textureList:[],
      VSHADER_SOURCE:`
      attribute vec3 a_Position;
      uniform mat4 u_ModelMatrix;
      uniform mat4 u_VPMatrix;
      void main(){
        gl_Position = u_VPMatrix * u_ModelMatrix * vec4( a_Position , 1.0 );
      }`,
      FSHADER_SOURCE:`
      #ifdef GL_ES
      precision mediump float;
      #endif
      void main(){
        gl_FragColor = vec4( 0.8,0.8,0.8 , 1.0 );
      }`
    }
    this.baseTextureList = baseTextureList//为处理为纹理的 纹理列表
    if(vs){this.material.VSHADER_SOURCE = vs}
    if(fs){this.material.FSHADER_SOURCE = fs}

    this.name = name
    this.program = cuonUtils.createProgram( gl, this.material.VSHADER_SOURCE ,         this.material.FSHADER_SOURCE )
    this.program.name = name + '的webglprogram';
    this.program.uuid = new Date().getTime();

    this.init_attribute(gl,attributeData)
    
    this.init_textureList(gl)

    }


    /* 1.0 初始化 attribute 数据及缓存 */
  init_attribute(gl,attributeData){
    //顶点
    this.program.a_Position = gl.getAttribLocation(this.program, "a_Position");
    this.geometry.vertexBuffer = this.initArrayBufferForLaterUse( attributeData.vertices, 3, gl.FLOAT);

    if(attributeData.normals){//法向量
      this.program.a_Normal = gl.getAttribLocation(this.program, "a_Normal");
      this.geometry.normalBuffer = this.initArrayBufferForLaterUse( attributeData.normals, 3, gl.FLOAT);
      if(!this.geometry.normalBuffer){console.log(this.program.name+' a_Normal attribute写入错误')}
    }
    if(attributeData.texCoords){//UV
      this.program.a_TexCoord = gl.getAttribLocation(this.program, "a_TexCoord");
      this.geometry.texCoordBuffer = this.initArrayBufferForLaterUse( attributeData.texCoords, 2, gl.FLOAT);
      if(!this.geometry.texCoordBuffer){console.log(this.program.name+' a_TexCoord attribute写入错误')}
    }

    //索引
    this.geometry.indexBuffer = this.initElementArrayBufferForLaterUse( attributeData.indices, gl.UNSIGNED_BYTE);
    if(!this.geometry.vertexBuffer){console.log(this.program.name+' a_Position attribute写入错误')}
    if(!this.geometry.indexBuffer){console.log(this.program.name+'indexBuffer 索引写入错误')}

    this.geometry.numIndices = attributeData.indices.length;

    //取消绑定焦点的数据
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
  }
  /* 1.0 unit 初始化缓冲区对象 */
  initElementArrayBufferForLaterUse(data, type) {
    let gl = this.gl;
    let buffer = gl.createBuffer(); //创建一个缓冲区对象
    if (!buffer) {
        console.log("无法创建缓冲区对象");
        return;
    }

    //将数据写入缓冲区
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW);

    buffer.type = type;

    return buffer;
  }
  /* 1.0 unit 初始化缓冲区对象 */
  initArrayBufferForLaterUse(data, num, type) {
    let gl = this.gl;
    let buffer = gl.createBuffer(); // 创建一个缓冲区对象
    if (!buffer) {
        console.log("无法创建缓冲区对象");
        return;
    }

    //将数据写入缓冲区对象
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);

    //保留必要的信息,以便后面使用
    buffer.num = num;
    buffer.type = type;

    return buffer;
  }

  /* 1.1 初始化纹理贴图 及 预获取 uniform 绑定 */
  init_textureList(gl){
    this.baseTextureList.forEach((item,index)=>{
      let texture;
      if(item.image){
        texture = this.useImageToGetTexture(gl,item.image,index+1)
      }else{
        texture = item
      }
      this.setUniformByTexture(index+1) //[现在不可用]
      this.material.textureList.push(texture)
    })
  }
  /* 1.1 unit 使用image获取纹理 @return webgltexture */
  useImageToGetTexture(gl,image,index){
    let texture = gl.createTexture();

    let target = "u_Sampler"+index
    let glTarget = "TEXTURE"+index
    this.gl.useProgram(this.program);
    this.program[target] = this.gl.getUniformLocation(this.program, target);
    // this.program.u_Sampler1 = this.gl.getUniformLocation(this.program, "u_Sampler1");
    if(!this.program[target]){
      console.log("无法获取到缓冲区对象");
      return null;
    }

    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);//1.对纹理图像进行Y轴反转 (默认是倒立的需要按Y轴反转)
    gl.activeTexture(gl[glTarget]);//2.开启index号纹理单元
    // gl.activeTexture(gl.TEXTURE1);//2.开启index号纹理单元
    gl.bindTexture(gl.TEXTURE_2D, texture);//3.向target绑定纹理对象
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);//4.配置纹理参数
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);//5.配置纹理图像

    // gl.uniform1i(this.program[target], index);//6.将index号纹理图像传递给着色器
    // gl.uniform1i(this.program.u_Sampler1, 1);//6.将index号纹理图像传递给着色器

    gl.bindTexture(gl.TEXTURE_2D, null);//7.取消绑定
    return texture
  }
  /* 1.1 unit 为program 设置纹理uniform 应该从1开始 因为0被用来做阴影贴图使用 [现在不可用] */
  setUniformByTexture(index){
    let target = "u_Sampler"+index
    this.gl.useProgram(this.program);
    this.program[target] = this.gl.getUniformLocation(this.program, target);
    if(!this.program[target]){
      console.log("无法获取到缓冲区对象");
      return null;
    }
    //将纹理存入到第一个纹理缓冲区
    this.gl.uniform1i(this.program[target], index);//6.将x号纹理图像传递给着色器
  }

  /* 
    2.0 初始化与设置 uniform 数据
    @param type 数据类型
    @param target uniform名称 (string)
    @param value  uniform值
    @param program  webgl program
    @return void
    https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/uniform
  */
  setUniform(type,target,value,newProgram){
    let program;
    if( newProgram ){
      program = newProgram
    }else{
      program = this.program
    }
    if(this.gl.program !== program){
      this.gl.useProgram(program);
    }

    let u_target;
    if(program[target] === void 0){
      u_target = this.gl.getUniformLocation( program, target );
      if (u_target < 0) {
        console.log(`${this.name}Mesh ${this.program.name}无法获取${target}uniform`);
        return;
      }
      program[target] = u_target
    }else{
      u_target = program[target]
    }
    
    if(type == 'bool'){

    }
    if(type == 'int'){

    }
    if(type == 'float'){
      this.gl.uniform1f(u_target,value)
    }
    if(type == 'vec3'){
      this.gl.uniform3fv(u_target,value)
    }
    if(type == 'mat4'){
      //                         是否转置transpose
      this.gl.uniformMatrix4fv(u_target,false,value)
    }
  }

  /* 3.0 绘制到canvas */
  draw(newprogram,shadowTexture){
    let gl = this.gl;
    let program;
    newprogram ? program = newprogram : program = this.program;
    // console.log(`绘制${this.name},使用着色器程序为${program.name}`)

    this.init_attributeVariable(gl, program.a_Position, this.geometry.vertexBuffer); //顶点坐标
    if(program.a_Normal && program.a_Normal!=-1){
      this.init_attributeVariable(gl, program.a_Normal, this.geometry.normalBuffer); //法向量
    }
    if(program.a_TexCoord && program.a_TexCoord!=-1){
      this.init_attributeVariable(gl, program.a_TexCoord, this.geometry.texCoordBuffer); //纹理坐标
      this.material.textureList.forEach((item,index)=>{
        let target = "TEXTURE"+(index+1)
        gl.activeTexture(gl[target]);
        gl.bindTexture(gl.TEXTURE_2D, item);
      })
    }
    //处理阴影
    if(shadowTexture!==void 0){
      gl.useProgram(program);
      program.u_Sampler0 = this.gl.getUniformLocation(program, "u_Sampler0");
      gl.uniform1i(program.u_Sampler0, 0);
      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, shadowTexture);
    }
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.geometry.indexBuffer);
    
    this.setUniform('mat4',"u_ModelMatrix",this.modelMatrix.elements,program)
    gl.drawElements(gl.TRIANGLES, this.geometry.numIndices, this.geometry.indexBuffer.type, 0);
  }

  /* 3.0 unit 绑定attribute */
  init_attributeVariable(gl, a_attribute, buffer) {
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.vertexAttribPointer(a_attribute, buffer.num, buffer.type, false, 0, 0);
    gl.enableVertexAttribArray(a_attribute);
  }



}

二、shadow.js

它负责初始化shadow渲染的帧缓存

import cuonUtils from '../js/cuon-utils'
import cuonMatrix from '../js/cuon-matrix'

class Shadow{
  constructor(gl,lightMesh){
    this.gl = gl
    this.lightMesh = lightMesh

    this.shadowProgram = ''

    //生成的纹理的分辨率,纹理必须是标准的尺寸 256*256 1024*1024  2048*2048
    this.resolution = 1024
    this.offset_width = 1024
    this.offset_height = 1024
    // this.resolution = 512
    // this.offset_width = 512
    // this.offset_height = 512

    this.initShaderPargram(gl)
    this.initShadowAttribute(gl)
    this.shadowProgram.name = 'shadowProgram'

    this.fbo = this.initFramebufferObject(gl);
    if(!this.fbo){
      console.log("shadow.js 无法设置帧缓冲区对象");
      return;
    }
    // console.log(this.fbo)

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, this.fbo.texture);

  }

  //初始化设置帧缓冲区对象
  initFramebufferObject(gl) {
    let framebuffer, texture, depthBuffer;

    //定义错误函数
    function error() {
        if(framebuffer) gl.deleteFramebuffer(framebuffer);
        if(texture) gl.deleteFramebuffer(texture);
        if(depthBuffer) gl.deleteFramebuffer(depthBuffer);
        return null;
    }

    //创建帧缓冲区对象
    framebuffer = gl.createFramebuffer();
    if(!framebuffer){
        console.log("shadow.js 无法创建帧缓冲区对象");
        return error();
    }

    //创建纹理对象并设置其尺寸和参数
    texture = gl.createTexture();
    if(!texture){
        console.log("shadow.js 无法创建纹理对象");
        return error();
    }

    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.offset_width, this.offset_height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    framebuffer.texture = texture;//将纹理对象存入framebuffer

    //创建渲染缓冲区对象并设置其尺寸和参数
    depthBuffer = gl.createRenderbuffer();
    if(!depthBuffer){
        console.log("shadow.js 无法创建渲染缓冲区对象");
        return error();
    }

    gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.offset_width, this.offset_height);

    //将纹理和渲染缓冲区对象关联到帧缓冲区对象上
    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER,depthBuffer);

    //检查帧缓冲区对象是否被正确设置
    var e = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
    if(gl.FRAMEBUFFER_COMPLETE !== e){
        console.log("shadow.js 渲染缓冲区设置错误"+e.toString());
        return error();
    }

    //取消当前的focus对象
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    gl.bindTexture(gl.TEXTURE_2D, null);
    gl.bindRenderbuffer(gl.RENDERBUFFER, null);

    return framebuffer;
  }

  //初始化阴影贴图着色器
  initShaderPargram(gl){
    let VSHADER_SOURCE = this.createVS()
    let FSHADER_SOURCE = this.createFS()

    this.shadowProgram = cuonUtils.createProgram( gl, VSHADER_SOURCE , FSHADER_SOURCE )
  }

  createVS(){
    return `
    attribute vec3 a_Position;
    uniform mat4 u_ModelMatrix;
    uniform mat4 u_VPMatrix;
    void main(){
      gl_Position = u_VPMatrix * u_ModelMatrix * vec4( a_Position , 1.0 );
    }`
  }
  createFS(){
    return `
    #ifdef GL_ES
    precision mediump float;
    #endif
    void main(){
      gl_FragColor = vec4( 0.0,0.0,0.0, gl_FragCoord.z );
      // gl_FragColor = vec4( 1.0,1.0,1.0, 1.0 );
    }`
  }

  getVPMatrix(){
    let position = this.lightMesh.position

    //设置视角矩阵的相关信息(视点,视线,上方向)
    let viewMatrix = new cuonMatrix.Matrix4();
    viewMatrix.setLookAt(position.x,position.y,position.z,0,0,0,0,1,0);

    //设置透视投影矩阵
    let projMatrix = new cuonMatrix.Matrix4();
    projMatrix.setPerspective(90,this.offset_width/this.offset_height,1,100);

    return projMatrix.multiply(viewMatrix)
  }

  //初始化attribute
  initShadowAttribute(gl){
    this.shadowProgram.a_Position = gl.getAttribLocation(this.shadowProgram, "a_Position");
    this.shadowProgram.u_VPMatrix = gl.getUniformLocation(this.shadowProgram, "u_VPMatrix");
    this.shadowProgram.u_ModelMatrix = gl.getUniformLocation(this.shadowProgram, "u_ModelMatrix");
  }
}

export default Shadow

三、使用这里练习使用的是vue2

其实可以对纹理进行封装     textureLoader.js

class TextureLoader{
  constructor(gl){
    this.gl = gl
  }
  loadImage(src,callback){
    let gl = this.gl
    let image = new Image()

    image.src = src

    image.onload = ()=>{
      // document.body.appendChild(image)
      let texture = gl.createTexture();
      // console.log(texture)
      // if(texture===''){console.log("TextureLoader.js 无法创建纹理缓冲区");return;}

      gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);//1.对纹理图像进行Y轴反转 (默认是倒立的需要按Y轴反转)
      // gl.activeTexture(gl.TEXTURE1);//2.开启index号纹理单元
      gl.bindTexture(gl.TEXTURE_2D, texture);//3.向target绑定纹理对象
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);//4.配置纹理参数
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);//5.配置纹理图像

      // gl.uniform1i(this.u_Sampler, 1);//6.将1号纹理图像传递给着色器

      gl.bindTexture(gl.TEXTURE_2D, null);//7.取消绑定

      callback(texture,image)
    }
  }
}

export default TextureLoader

<template>
  <div>
    <canvas id="mycanvas"></canvas>
  </div>
</template>

<script>
import Stats from './js/stats'//刷新率展示
import cuonMatrix from './js/cuon-matrix'
import Mesh from './units/mesh.js'
import TextureLoader from './units/textureLoader.js'
import Shadow from './units/shadow.js'
export default {
  data () {
    return {
      canvas:'',
      gl:'',
      stats:'',

      VPMatrix:'',

      texture:'',

      shadow:'',

      clock:0,
      speed:1,

      myMesh01:'',
      myMesh02:'',
      myMesh03:'',
    }
  },
  mounted () {
    this.$nextTick(()=>{
      this.init()
    })
  },
  methods: {
    init(){
      let canvas = document.getElementById('mycanvas')
      this.canvas = canvas
      canvas.width = 300
      canvas.height = 300
      canvas.style.border = '10px solid yellow'

      let gl = canvas.getContext('webgl')
      this.gl = gl

      this.initStats()

      // 初始化纹理加载器
      let textureLoader = new TextureLoader(gl)
      textureLoader.loadImage(require("../../assets/wenli.jpg"),(texture,image)=>{
        // this.texture = {image:image}
        this.texture = texture
        this.main()
      })
    },
    main(){
      let gl = this.gl
      if(!gl){return this.$message.error('该浏览器不支持')}
      
      // 获取attribute数据
      let a01 = this.getAttributeData01()
      let a02 = this.getAttributeData02()

      // 创建mesh
      let myMesh01VS = this.myMesh01VS()
      let myMesh01FS = this.myMesh01FS()
      this.myMesh01 = new Mesh( gl , '我的mesh01' , a01 , myMesh01VS , myMesh01FS , [this.texture] )
      this.myMesh01.position.set(0,0,4)
      this.myMesh01.scale.set(0.5,0.5,0.5)
      // console.log("this.myMesh01",this.myMesh01)

      let myMesh02VS = this.myMesh02VS()
      let myMesh02FS = this.myMesh02FS()
      this.myMesh02 = new Mesh( gl , '我的mesh02' , a02 , myMesh02VS , myMesh02FS )
      this.myMesh02.position.set(0,0,0)
      this.myMesh02.scale.set(4,4,4)
      
      this.myMesh03 = new Mesh( gl , '我的mesh02' , a02 )
      this.myMesh03.position.set(0,0,10)
      this.myMesh03.scale.set(0.1,0.1,0.1)

      this.getviewprojMatrix()

      //初始化阴影
      this.shadow = new Shadow(gl,this.myMesh03)   

      //设置底色 和隐藏面消除
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      gl.enable(gl.DEPTH_TEST);
      this.animation()
    },
    animation(){
      this.myMesh01.position.set(0,this.clock/40,4)

      this.stats.update();//更新刷新率插件
      this.draw(this.gl)
      window.requestAnimationFrame(this.animation);
    },
    draw(gl){
      let lightVPmat4 = this.shadow.getVPMatrix()

      gl.bindFramebuffer(gl.FRAMEBUFFER, this.shadow.fbo);
      gl.viewport(0.0,0.0,this.shadow.offset_width,this.shadow.offset_height);
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

      this.myMesh01.setUniform('mat4',"u_VPMatrix",lightVPmat4.elements , this.shadow.shadowProgram)
      this.myMesh01.draw(this.shadow.shadowProgram)


      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
      gl.viewport(0.0, 0.0, 300, 300);
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

      this.myMesh01.setUniform('mat4',"u_VPMatrix",this.VPMatrix.elements)
      this.myMesh01.draw()

      this.myMesh02.setUniform('mat4',"u_VPMatrix",this.VPMatrix.elements)
      this.myMesh02.setUniform('mat4',"u_LightVPMatrix",lightVPmat4.elements)
      this.myMesh02.draw(undefined,this.shadow.fbo.texture)
    },
    /* 
      获取vp矩阵
    */
    getviewprojMatrix(){
      let canvas = this.canvas
      //设置视角矩阵的相关信息(视点,视线,上方向)
      let viewMatrix = new cuonMatrix.Matrix4();
      viewMatrix.setLookAt(-4,0,6,0,0,0,0,1,0);

      //设置透视投影矩阵
      let projMatrix = new cuonMatrix.Matrix4();
      projMatrix.setPerspective(90,canvas.width/canvas.height,1,100);

      this.VPMatrix =  projMatrix.multiply(viewMatrix);
    },
    /* 获取立方体数据 */
    getAttributeData01(){
      let attributeData = {}
      attributeData.vertices = new Float32Array([   // 单色立方体的顶点位置数据
        1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0,    // v0-v1-v2-v3 front
        1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0,    // v0-v3-v4-v5 right
        1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0,    // v0-v5-v6-v1 up
        -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0,    // v1-v6-v7-v2 left
        -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,    // v7-v4-v3-v2 down
        1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0     // v4-v7-v6-v5 back
      ]);
      attributeData.normals = new Float32Array([   // 单色立方体的法相量
        0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,     // v0-v1-v2-v3 front
        1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,     // v0-v3-v4-v5 right
        0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,     // v0-v5-v6-v1 up
        -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,     // v1-v6-v7-v2 left
        0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0,     // v7-v4-v3-v2 down
        0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0      // v4-v7-v6-v5 back
      ]);
      attributeData.texCoords = new Float32Array([
        1.0, 1.0,   0.0, 1.0,   0.0, 0.0,   1.0, 0.0,    // v0-v1-v2-v3 front
        0.0, 1.0,   0.0, 0.0,   1.0, 0.0,   1.0, 1.0,    // v0-v3-v4-v5 right
        1.0, 0.0,   1.0, 1.0,   0.0, 1.0,   0.0, 0.0,    // v0-v5-v6-v1 up
        1.0, 1.0,   0.0, 1.0,   0.0, 0.0,   1.0, 0.0,    // v1-v6-v7-v2 left
        0.0, 0.0,   1.0, 0.0,   1.0, 1.0,   0.0, 1.0,    // v7-v4-v3-v2 down
        0.0, 0.0,   1.0, 0.0,   1.0, 1.0,   0.0, 1.0     // v4-v7-v6-v5 back
      ]);

      attributeData.indices = new Uint8Array([// 索引值
        0, 1, 2, 0, 2, 3,    // front
        4, 5, 6, 4, 6, 7,    // right
        8, 9, 10, 8, 10, 11,    // up
        12, 13, 14, 12, 14, 15,    // left
        16, 17, 18, 16, 18, 19,    // down
        20, 21, 22, 20, 22, 23     // back
      ]);
      return attributeData
    },
    /* 获取纹理测试正方面数据 */
    getAttributeData02(){
      let attributeData = {}
      attributeData.vertices = new Float32Array([ 
        1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, -1.0, 0.0 , 1.0, -1.0, 0.0
      ]);
      attributeData.normals = new Float32Array([ 
        0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0
      ]);
      attributeData.texCoords = new Float32Array([
        1.0, 1.0,   0.0, 1.0,  0.0, 0.0,   1.0, 0.0
      ]);
      attributeData.indices = new Uint8Array([
        0, 1, 2, 0,2,3
      ]);
      return attributeData
    },

    /* 初始化刷新率 */
    initStats(){
      let stats = new Stats();
      this.stats = stats
      stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
      document.body.appendChild( stats.dom );
    },

    /* 着色器 */
    myMesh01VS(){
      return `
      attribute vec3 a_Position;
      attribute vec3 a_Normal;
      attribute vec2 a_TexCoord;
      uniform mat4 u_ModelMatrix;
      uniform mat4 u_VPMatrix;
      varying vec2 v_TexCoord;
      void main(){
        gl_Position = u_VPMatrix * u_ModelMatrix * vec4( a_Position , 1.0 );
        v_TexCoord = a_TexCoord;
      }`
    },
    myMesh01FS(){
      return `
      #ifdef GL_ES
      precision mediump float;
      #endif
      uniform sampler2D u_Sampler1;
      varying vec2 v_TexCoord;
      void main(){
        vec4 color = texture2D(u_Sampler1, v_TexCoord);
        // gl_FragColor = vec4( 0.8,0.8,0.8 , 1.0 );
        gl_FragColor = color ;
        // gl_FragColor = vec4( v_TexCoord ,0.0,1.0) ;
      }`
    },

    myMesh02VS(){
      return `
      attribute vec3 a_Position;
      attribute vec3 a_Normal;
      attribute vec2 a_TexCoord;
      uniform mat4 u_ModelMatrix;
      uniform mat4 u_VPMatrix;
      uniform mat4 u_LightVPMatrix;
      varying vec2 v_TexCoord;
      varying vec4 v_PositionFromLight;
      void main(){
        gl_Position = u_VPMatrix * u_ModelMatrix * vec4( a_Position , 1.0 );
        v_TexCoord = a_TexCoord;
        v_PositionFromLight = u_LightVPMatrix * u_ModelMatrix * vec4( a_Position , 1.0 );
      }`
    },
    myMesh02FS(){
      return `
      #ifdef GL_ES
      precision mediump float;
      #endif
      uniform sampler2D u_Sampler0;
      varying vec2 v_TexCoord;
      varying vec4 v_PositionFromLight;
      void main(){
        vec3 shadowCoord = (v_PositionFromLight.xyz/v_PositionFromLight.w)/2.0 + 0.5;
        vec4 shadowMap = texture2D(u_Sampler0, shadowCoord.xy);
        float depth = shadowMap.a;

        float visibility = (shadowCoord.z > depth + 0.005) ? 0.5 : 1.0;        
        gl_FragColor = vec4(vec3(0.0,1.0,0.0) * visibility, 1.0);
      }`
    },
  }
}
</script>

<style>

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值