shadowMap 简单回顾_create shadow maps-程序员宅基地

技术标签: webgl  

编程指南: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);
 }
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_36091277/article/details/116866029

智能推荐

CentOS8安装Memcached数据库_centos8安装memcache目录-程序员宅基地

文章浏览阅读835次。想要学习分布式,所以选择从memcached数据库开始入手,在做学习的准备工作时,一定要先学会如何配置和安装Linux系统和memcached数据库。Linux版本本人采用了CentOS系统,并且是最新版本的centos8。对于一个Linux和分布式小白来讲,在安装memcached数据库的时候突然出现无可预料的错误,真的是措手不及。 下面我将描述一下如何使用CentOS8系统进行memcached数据库的安装以及遇到问题的解决方法。1、先进入到Linux系统的/usr/local/src/文件..._centos8安装memcache目录

PPP/PPPOE源码阅读笔记_ppp_start_xmit+0x1a4/0x228-程序员宅基地

文章浏览阅读4.1k次,点赞9次,收藏35次。一.缘起 本人工作与网关产品有关,经常会接触到pppoe协议,但对ppp和pppoe是如何实现的不甚了解。在网上查找相关的文章大多是描述ppp/pppoe协议的具体内容和数据流大的流程,而未过多的涉及内核中pppoe驱动和ppp驱动代码实现的细节,正好这段时间在看毛德操和胡希明老师的《Linux内核源代码情景分析》,看了内核中的终端驱动,遂决定仔细学习一下PPP/PPPOE驱动这一..._ppp_start_xmit+0x1a4/0x228

主流的CPU架构_cpu体系架构-程序员宅基地

文章浏览阅读1.1w次,点赞14次,收藏53次。主流CPU架构_cpu体系架构

jzoj3692. 【SRM 611】ElephantDrinking-程序员宅基地

文章浏览阅读205次。题目描述Description这里有一个n*n 的平原,其中一些格子有泉水。你会得到一个string 字符串组,作为地图被用于描述平原。string 有n 个字符串,每个字符串长度为n,每个字符为0 到9 的数字。数字0 代表这个格子没有水;数字1 到9 代表泉水,并且数字为泉眼出水的速率。例如,数字5 表示一个每单位时间产生5 单位水的泉水。平原周围有4n 头大象:绕着平原的边缘,每一格边...

7,城市气候与海洋的关系研究-程序员宅基地

文章浏览阅读456次。导入包import numpy as npimport pandas as pdfrom pandas import Series,DataFrameimport matplotlib.pyplot as plt%matplotlib inline# 设置显示汉字import sysreload(sys)sys.setdefaultenco..._(1)分析城市气温与海洋距离的关系,并画图显示

马士兵网络安全大师课2023-程序员宅基地

文章浏览阅读198次。获取漏洞信息:首先需要获取有关CVE漏洞的详细信息,包括漏洞的描述、影响范围、攻击方式等。在复现CVE漏洞时,需要配置合适的攻击向量,以便模拟真实的攻击场景。分析结果:最后,需要对复现结果进行分析,以了解漏洞的性质、影响范围和可能的解决方案。需要注意的是,CVE漏洞复现需要具备一定的技术能力和经验。验证漏洞:在实施攻击后,需要验证是否成功复现了CVE漏洞。这可能包括发送特定的恶意请求、利用特定的漏洞等。构建环境:为了复现CVE漏洞,需要构建一个与漏洞相关的环境。这可能包括安装特定的软件、配置特定的网络等。

随便推点

深度学习环境搭建入门环境搭建(pytorch版本)_深度学习pytorch搭建-程序员宅基地

文章浏览阅读474次,点赞3次,收藏3次。本文介绍了如何从零开始如何搭建深度学习环境的过程。先是介绍了Anaconda的安装,这是一个用于创建Python虚拟环境的工具,使环境管理更加便捷。接下来是PyCharm的安装,这是一个Python集成开发环境,适用于编码和项目管理。同时请关注显卡驱动、Python版本、深度学习框架版本和CuDNN版本之间的兼容性,还介绍了Jupyter Notebook,一种交互式编程环境,用于实验和笔记,并且讨论了在GitHub上创建代码库和协同工作的过程。_深度学习pytorch搭建

【Excel】用excel生成矩阵_excel 共现矩阵-程序员宅基地

文章浏览阅读1.3w次。1、使用sql语句生成group by数据,复制到Excel Sheet中例如A B 3B D 4C A 2D B 12、创建新sheet,粘贴上述数据到新sheet2.1 分别选中第一列、第二列,进行操作:数据--》删除重复项,得到矩阵的横坐标和纵坐标的数据2.3 制作矩阵的坐标轴:复制第二列数据,右键单元格:选择性粘贴--》转置2.4 生成数据,例如_excel 共现矩阵

【ESP8266-01】MQTT连接百度云-进阶(物可视)_百度云物可视-程序员宅基地

文章浏览阅读4.7k次。上一章 【ESP8266-01】MQTT连接百度云(天工物接入)ESP8266-01 MQTT连接百度云-进阶(物可视)前言前边我们讲了MQTT连接百度云了,也学会了如何上传数据,那么我们要玩一些更高大上的,让这些数据用模型替代出来,同时看起来也更加的美观,就像下图所示。好了,本章节我们就来学习如何让数据可视化起来。1.创建工程1.1 打开“物联网数据可视化”1.2 创建工作区工作区的名称自行命名;我这里命名为“hello”;1.3 创建仪表盘为仪表盘命名,下边有多个模板可以选择_百度云物可视

蒙特卡洛算法及简单应用_给定曲线和曲线,曲线的交点为:、。曲线围成平面有限区域,用蒙特卡罗方法计算区域-程序员宅基地

文章浏览阅读1w次,点赞10次,收藏69次。基本概念蒙特卡罗方法又称统计模拟法、随机抽样技术,是一种随机模拟方法,以概率和统计理论方法为基础的一种计算方法,是使用随机数(或伪随机数)来解决很多计算问题的方法。将所求解的问题同一定的概率模型相联系,用电子计算机实现统计模拟或抽样,以获得问题的近似解。为象征性地表明这一方法的概率统计特征,故借用赌城蒙特卡罗命名。基本思想:当所求问题的解是某个事件的概率,或者是某个随机变量的数学期望,_给定曲线和曲线,曲线的交点为:、。曲线围成平面有限区域,用蒙特卡罗方法计算区域

java 调用 rar压缩文件-程序员宅基地

文章浏览阅读385次。[code="java"]public static boolean winrar(String winrarfile, String foler) { //winrar软件的安装路径 String rarPath = "C:\\Program Files\\WinRAR\\WinRAR.exe"; String cmd=""; // cmd=r..._java调用winrar提示未知选项mx10385760

有没有一种间隔循环提醒的便签APP-程序员宅基地

文章浏览阅读837次。在快节奏的社会,每天醒来都有一堆事情需要处理。如果不小心把事情忘记了,就会造成很严重的后果。像纸质便签本这种只有记录没有提醒功能的工具,已经不符合现代人的期待。提醒功能强大的记事便签软件,才是我们所需要的。职场上非常流行的便签APP是敬业签,敬业签除了可以记录文本内容,以及上传图片、声音、文件附件外,还可以给每条事项添加提醒时间。在手机敬业签上,在输入框左下角点闹钟图标,或者左滑已保存的内容,都可以添加提醒时间。敬业签的提醒模式是多样化的,可以设置单次提醒、按天/周/月/季度/年/自定义周期重复_循环提醒