shadowMap 简单回顾

编程指南:shadowMap示例连接
编程指南部分代码
给与想象的空间

获取gl变量

var canvas = document.getElementById('webgl');
var gl = getWebGLContext(canvas);

获取Plane、Triangle顶点缓冲区,颜色缓冲区,索引缓冲区

var triangle = initVertexBuffersForTriangle(gl); //三角形
var plane = initVertexBuffersForPlane(gl);   //平面

//不推荐这么写...当然我也不知道怎么写更好
//将顶点数组、颜色数组、索引数组 转为顶点缓冲区,颜色缓冲区,索引缓冲区
function initVertexBuffersForTriangle(gl) {
  // Create a triangle
  //       v2
  //      / | 
  //     /  |
  //    /   |
  //  v0----v1
  // Vertex coordinates
  var vertices = new Float32Array([-0.8, 3.5, 0.0,  0.8, 3.5, 0.0,  0.0, 3.5, 1.8]);
  // Colors
  var colors = new Float32Array([1.0, 0.5, 0.0,  1.0, 0.5, 0.0,  1.0, 0.0, 0.0]);    
  // Indices of the vertices
  var indices = new Uint8Array([0, 1, 2]);
  var o = new Object();  // Utilize Object object to return multiple buffer objects together
  // Write vertex information to buffer object
  o.vertexBuffer = initArrayBufferForLaterUse(gl, vertices, 3, gl.FLOAT);
  o.colorBuffer = initArrayBufferForLaterUse(gl, colors, 3, gl.FLOAT);
  o.indexBuffer = initElementArrayBufferForLaterUse(gl, indices, gl.UNSIGNED_BYTE);
  if (!o.vertexBuffer || !o.colorBuffer || !o.indexBuffer) return null; 
  o.numIndices = indices.length;
  // Unbind the buffer object
  gl.bindBuffer(gl.ARRAY_BUFFER, null);
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
  return o;
}
//这个是加载Plane
function initVertexBuffersForPlane(gl) {
   // Create a plane
   //  v1------v0
   //  |        | 
   //  |        |
   //  |        |
   //  v2------v3
   // Vertex coordinates
   var vertices = new Float32Array([
     3.0, -1.7, 2.5,  
     -3.0, -1.7, 2.5,  
     -3.0, -1.7, -2.5,   
     3.0, -1.7, -2.5    // v0-v1-v2-v3
   ]);
   // Colors
   var colors = 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
   ]);
   // Indices of the vertices
   var indices = new Uint8Array([0, 1, 2,   0, 2, 3]);
   var o = new Object(); // Utilize Object object to return multiple buffer objects together
   // Write vertex information to buffer object
   o.vertexBuffer = initArrayBufferForLaterUse(gl, vertices, 3, gl.FLOAT);
   o.colorBuffer = initArrayBufferForLaterUse(gl, colors, 3, gl.FLOAT);
   o.indexBuffer = initElementArrayBufferForLaterUse(gl, indices, gl.UNSIGNED_BYTE);
   if (!o.vertexBuffer || !o.colorBuffer || !o.indexBuffer) return null; 
   o.numIndices = indices.length;
   // Unbind the buffer object
   gl.bindBuffer(gl.ARRAY_BUFFER, null);
   gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
   return o;
 }
 function initArrayBufferForLaterUse(gl, data, num, type) {
   // Create a buffer object
   var buffer = gl.createBuffer();
   if (!buffer) {
     console.log('Failed to create the buffer object');
     return null;
   }
   gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
   gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
   buffer.num = num;
   buffer.type = type;
   return buffer;
 }
 function initElementArrayBufferForLaterUse(gl, data, type) {
   var buffer = gl.createBuffer();
   if (!buffer) {
     console.log('Failed to create the buffer object');
     return null;
   }
   gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
   gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW);
   buffer.type = type;
   return buffer;
 }

先获取fbo,后面用

  • fbo还有一种方式绑定
 var fbo = initFramebufferObject(gl);
 
 //texture depthBuffer 返回fbo
 function initFramebufferObject(gl) {
   var texture = gl.createTexture(); // 纹理创建 后面拿来用的
   gl.bindTexture(gl.TEXTURE_2D, texture); // Bind the object to target
   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

   var depthBuffer = gl.createRenderbuffer(); // 创建渲染缓冲区 用来渲染的
   gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); // Bind the object to target
   gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT); //都是深度吗?

   var framebuffer = gl.createFramebuffer(); //帧缓冲区 有个有点展示的意思
   framebuffer.texture = texture; // Store the texture object
   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); //判断是否正确配置
   return framebuffer;
 }

变量的声明

var OFFSCREEN_WIDTH = 2048, OFFSCREEN_HEIGHT = 2048;
var LIGHT_X = 0, LIGHT_Y = 7, LIGHT_Z = 2; // Position of the light source
var currentAngle = 0.0; // Current rotation angle (degrees)
var mvpMatrixFromLight_t = new Matrix4(); // A model view projection matrix from light source (for triangle)
var mvpMatrixFromLight_p = new Matrix4(); // A model view projection matrix from light source (for plane)

深度材质,用在平面和三角面上的,然后给fbo获取为那个角度的贴图

 var shadowProgram = createProgram(gl, SHADOW_VSHADER_SOURCE, SHADOW_FSHADER_SOURCE);
 var SHADOW_VSHADER_SOURCE =
   'attribute vec4 a_Position;\n' +
   'uniform mat4 u_MvpMatrix;\n' +
   'void main() {\n' +
   '  gl_Position = u_MvpMatrix * a_Position;\n' +
   '}\n';
 var SHADOW_FSHADER_SOURCE =
   '#ifdef GL_ES\n' +
   'precision mediump float;\n' +
   '#endif\n' +
   'void main() {\n' +
   '  gl_FragColor = vec4(gl_FragCoord.z, 0.0, 0.0, 0.0);\n' + //网格材质的颜色只写入z值
   '}\n';
使用材质
shadowProgram.a_Position = gl.getAttribLocation(shadowProgram, 'a_Position');
shadowProgram.u_MvpMatrix = gl.getUniformLocation(shadowProgram, 'u_MvpMatrix');
gl.activeTexture(gl.TEXTURE0); // Set a texture object to the texture unit
gl.bindTexture(gl.TEXTURE_2D, fbo.texture); //为啥要在这里绑定呢
var viewProjMatrixFromLight = new Matrix4(); // Prepare a view projection matrix for generating a shadow map
viewProjMatrixFromLight.setPerspective(70.0, OFFSCREEN_WIDTH/OFFSCREEN_HEIGHT, 1.0, 100.0);
viewProjMatrixFromLight.lookAt(LIGHT_X, LIGHT_Y, LIGHT_Z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
drawcall
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); // Change the drawing destination to FBO
gl.viewport(0, 0, OFFSCREEN_HEIGHT, OFFSCREEN_HEIGHT); // Set view port for FBO
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);   // Clear FBO    
gl.useProgram(shadowProgram); // Set shaders for generating a shadow map
drawTriangle(gl, shadowProgram, triangle, currentAngle, viewProjMatrixFromLight);
//mvpMatrixFromLight_t.set(g_mvpMatrix); // Used later
drawPlane(gl, shadowProgram, plane, viewProjMatrixFromLight);
mvpMatrixFromLight_p.set(g_mvpMatrix); // Used later

生成阴影材质,用在平面和三角面上的

图一

  var normalProgram = createProgram(gl, VSHADER_SOURCE, FSHADER_SOURCE);
  // Vertex shader program for regular drawing
  var VSHADER_SOURCE =
    'attribute vec4 a_Position;\n' +
    'attribute vec4 a_Color;\n' +
    'uniform mat4 u_MvpMatrix;\n' +
    'uniform mat4 u_MvpMatrixFromLight;\n' +
    'varying vec4 v_PositionFromLight;\n' +
    'varying vec4 v_Color;\n' +
    'void main() {\n' +
    '  gl_Position = u_MvpMatrix * a_Position;\n' + 
    '  v_PositionFromLight = u_MvpMatrixFromLight * a_Position;\n' + //相对于光点的矩阵
    '  v_Color = a_Color;\n' +
    '}\n';

  // Fragment shader program for regular drawing
  var FSHADER_SOURCE =
    '#ifdef GL_ES\n' +
    'precision mediump float;\n' +
    '#endif\n' +
    'uniform sampler2D u_ShadowMap;\n' + //深度贴图
    'varying vec4 v_PositionFromLight;\n' +
    'varying vec4 v_Color;\n' +
    'void main() {\n' +
    '  vec3 shadowCoord = (v_PositionFromLight.xyz/v_PositionFromLight.w)/2.0 + 0.5;\n' +  //
    '  vec4 rgbaDepth = texture2D(u_ShadowMap, shadowCoord.xy);\n' + //这一步可看图一来理解 能上贴图(rgbaDepth是带有深度信息的)的地方
    '  float visibility = (shadowCoord.z > rgbaDepth.r + 0.005) ? 0.7 : 1.0;\n' + //实际深度与贴图上的深度要深得话 就会有阴影 乘0.7是为了更暗
    '  gl_FragColor = vec4(v_Color.rgb * visibility, v_Color.a);\n' + //
    '}\n';

使用材质
normalProgram.a_Position = gl.getAttribLocation(normalProgram, 'a_Position');
normalProgram.a_Color = gl.getAttribLocation(normalProgram, 'a_Color');
normalProgram.u_MvpMatrix = gl.getUniformLocation(normalProgram, 'u_MvpMatrix');
normalProgram.u_MvpMatrixFromLight = gl.getUniformLocation(normalProgram, 'u_MvpMatrixFromLight');
normalProgram.u_ShadowMap = gl.getUniformLocation(normalProgram, 'u_ShadowMap');
var viewProjMatrix = new Matrix4();          // Prepare a view projection matrix for regular drawing
viewProjMatrix.setPerspective(45, canvas.width/canvas.height, 1.0, 100.0);
viewProjMatrix.lookAt(0.0, 9.0, 9.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
drawcall
gl.bindFramebuffer(gl.FRAMEBUFFER, null); // Change the drawing destination to color buffer
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);    // Clear color and depth buffer
gl.useProgram(normalProgram); // Set the shader for regular drawing
gl.uniform1i(normalProgram.u_ShadowMap, 0);  // Pass 0 because gl.TEXTURE0 is enabled�る
//gl.uniformMatrix4fv(normalProgram.u_MvpMatrixFromLight, false, mvpMatrixFromLight_t.elements);
drawTriangle(gl, normalProgram, triangle, currentAngle, viewProjMatrix);
gl.uniformMatrix4fv(normalProgram.u_MvpMatrixFromLight, false, mvpMatrixFromLight_p.elements);
drawPlane(gl, normalProgram, plane, viewProjMatrix);

drawcall的一些方法

 // Coordinate transformation matrix
 var g_modelMatrix = new Matrix4();
 var g_mvpMatrix = new Matrix4();
 function drawTriangle(gl, program, triangle, angle, viewProjMatrix) {
   // Set rotate angle to model matrix and draw triangle
   g_modelMatrix.setRotate(angle, 0, 1, 0);
   draw(gl, program, triangle, viewProjMatrix);
 }
 function drawPlane(gl, program, plane, viewProjMatrix) {
   // Set rotate angle to model matrix and draw plane
   g_modelMatrix.setRotate(-45, 0, 1, 1);
   draw(gl, program, plane, viewProjMatrix);
 }
 function draw(gl, program, o, viewProjMatrix) {
   initAttributeVariable(gl, program.a_Position, o.vertexBuffer);
   if (program.a_Color != undefined) // If a_Color is defined to attribute
     initAttributeVariable(gl, program.a_Color, o.colorBuffer);
   gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, o.indexBuffer);
   // Calculate the model view project matrix and pass it to u_MvpMatrix
   g_mvpMatrix.set(viewProjMatrix);
   g_mvpMatrix.multiply(g_modelMatrix);
   gl.uniformMatrix4fv(program.u_MvpMatrix, false, g_mvpMatrix.elements);
   gl.drawElements(gl.TRIANGLES, o.numIndices, gl.UNSIGNED_BYTE, 0);
 }
 // Assign the buffer objects and enable the assignment
 function initAttributeVariable(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);
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值