提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
个人学习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>