WebGL简易教程(十三):帧缓存对象(离屏渲染)
目录
- 1. 概述
- 2. 示例
- 2.1. 着色器部分
- 2.2. 初始化/准备工作
- 2.2.1. 着色器切换
- 2.2.2. 帧缓冲区
- 2.3. 绘制函数
- 2.3.1. 初始化顶点数组
- 2.3.2. 传递非公用随帧不变的数据
- 2.3.3. 逐帧绘制
- 3. 结果
- 4. 参考
1. 概述
事物是普遍联系的。为了达到更加真实的渲染效果,很多时候需要利用被渲染物体在其他状态下的中间渲染结果,处理到最终显示的渲染场景中。这种中间渲染结果,就保存在帧缓冲区对象(framebuffer object,简称FBO)中,用来替代颜色缓冲区或深度缓存区。由于其结果并不直接被显示出来,所以这种技术也被称为离屏绘制(offscreen drawing)。
在之前的教程实例中,地形的颜色信息都是来自于顶点缓冲区对象。而在这篇教程中,准备写出这样一个示例:分别在帧缓冲区和颜色缓冲区中绘制同一块地形,颜色缓冲区的颜色信息不通过顶点缓冲区获取而通过帧缓冲区获取。这个简单的示例并没有具体的实际意义,但是能更好的理解FBO,FBO是后续更高级技术的基础。
2. 示例
示例的完整代码太长,这里就不放出来了,可以在文章尾部提供的地址自行下载;这里主要讲解其中的关键部分。
2.1. 着色器部分
这里定义了两组着色器,一组是绘制在帧缓冲区的:
// 顶点着色器程序-绘制到帧缓存
var FRAME_VSHADER_SOURCE ='attribute vec4 a_Position;\n' + //位置'attribute vec4 a_Color;\n' + //颜色'uniform mat4 u_MvpMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +' gl_Position = u_MvpMatrix * a_Position;\n' + // 设置顶点坐标' v_Color = a_Color;\n' +'}\n';// 片元着色器程序-绘制到帧缓存
var FRAME_FSHADER_SOURCE ='precision mediump float;\n' +'varying vec4 v_Color;\n' +'void main() {\n' + ' gl_FragColor = v_Color;\n' + //将深度保存在FBO中'}\n';
可以看到这段着色器程序与绘制在颜色缓冲区的着色器没有区别。另外一组是正常绘制在颜色缓冲区的:
// 顶点着色器程序
var VSHADER_SOURCE ='attribute vec4 a_Position;\n' + //位置'attribute vec4 a_Color;\n' + //颜色'attribute vec4 a_Normal;\n' + //法向量'uniform mat4 u_MvpMatrix;\n' + 'varying vec4 v_PositionFromLight;\n' +'void main() {\n' +' gl_Position = u_MvpMatrix * a_Position;\n' +' v_PositionFromLight = gl_Position;\n' +'}\n';// 片元着色器程序
var FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'uniform sampler2D u_Sampler;\n' + //颜色贴图'varying vec4 v_PositionFromLight;\n' +'void main() {\n' +//获取颜色贴图中的值' vec3 shadowCoord = (v_PositionFromLight.xyz/v_PositionFromLight.w)/2.0 + 0.5;\n' +' gl_FragColor = texture2D(u_Sampler, shadowCoord.xy);\n' +'}\n';
这里可以看到最终位置仍然来自顶点数组,颜色却是从一个纹理对象插值出来的。这个纹理对象正是帧缓冲区中关联的纹理对象,它是在帧缓冲对象绘制之后传递过来的。
注意这里关于纹理坐标的计算,在《WebGL简易教程(五):图形变换(模型、视图、投影变换)》这篇教程中曾经提到过,在经过顶点着色器之后,顶点坐标会归一化到-1到1之间;而纹理坐标是在0到1之间的,所以这里需要坐标变换一下。
2.2. 初始化/准备工作
首先仍然是进行一些初始化操作。获取上下文后创建着色器,并初始化帧缓冲对象(FBO):
// 获取 <canvas> 元素var canvas = document.getElementById('webgl');// 获取WebGL渲染上下文var gl = getWebGLContext(canvas);if (!gl) {console.log('Failed to get the rendering context for WebGL');return;}//初始化两个着色器,drawProgram绘制到界面,frameProgram绘制到帧缓存var drawProgram = createProgram(gl, VSHADER_SOURCE, FSHADER_SOURCE);var frameProgram = createProgram(gl, FRAME_VSHADER_SOURCE, FRAME_FSHADER_SOURCE);if (!drawProgram || !frameProgram) {console.log('Failed to intialize shaders.');return;}//从着色器中获取地址,保存到对应的变量中GetProgramLocation(gl, drawProgram, frameProgram);// 初始化帧缓冲区对象 (FBO)var fbo = initFramebufferObject(gl);if (!fbo) {console.log('Failed to intialize the framebuffer object (FBO)');return;}// 开启深度测试gl.enable(gl.DEPTH_TEST);// 指定清空<canvas>的颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);//清空颜色和深度缓冲区gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
这里的函数GetProgramLocation是功能将从着色器获取的数据地址保存起来,因为涉及到一些切换着色器再分配数据的操作,保存到变量中方便一些:
//从着色器中获取地址,保存到对应的变量中
function GetProgramLocation(gl, drawProgram, frameProgram) {// Get the storage location of attribute variables and uniform variables drawProgram.a_Position = gl.getAttribLocation(drawProgram, 'a_Position');drawProgram.u_MvpMatrix = gl.getUniformLocation(drawProgram, 'u_MvpMatrix');if (drawProgram.a_Position < 0 || !drawProgram.u_MvpMatrix) {console.log('Failed to get the storage location of a_Position, u_MvpMatrix');//return;}frameProgram.a_Position = gl.getAttribLocation(frameProgram, 'a_Position');frameProgram.a_Color = gl.getAttribLocation(frameProgram, 'a_Color');frameProgram.u_MvpMatrix = gl.getUniformLocation(frameProgram, 'u_MvpMatrix');if (frameProgram.a_Position < 0 || frameProgram.a_TexCoord < 0 || !frameProgram.u_MvpMatrix) {console.log('Failed to get the storage location of a_Position, a_Color, u_MvpMatrix');//return;}
}
2.2.1. 着色器切换
在示例中实际进行了两次绘制操作,分别在帧缓冲区和颜色缓冲区中绘制了一遍。因此,需要用到两组不同的着色器。但是同一时间内只能用一组着色器进行绘制工作,这里就涉及到一个着色器切换的问题。
2.2.1.1. 初始化
在之前的例子当中,都是通过WebGL组件cuon-utils中的函数initShaders来初始化着色器。这个函数实际上包含了创建着色器程序功能函数createProgram(),以及设置当前着色器函数gl.useProgram():
function initShaders(gl, vshader, fshader) {var program = createProgram(gl, vshader, fshader);if (!program) {console.log('Failed to create program');return false;}gl.useProgram(program);gl.program = program;return true;
}
在程序初始化的时候只需要创建着色器函数createProgram()就可以了,在需要传输数据和绘制的时候再去设置当前的着色器gl.useProgram()。
2.2.1.2. 顶点缓冲区
除此之外,顶点缓冲区的使用也有所改变。在之前的教程《WebGL简易教程(三):绘制一个三角形(缓冲区对象)》中介绍过使用顶点缓冲区的五个步骤:
- 创建缓冲区对象(gl.createBuffer())
- 绑定缓冲区对象(gl.bindBuffer())
- 将数据写入缓冲区对象(gl.bufferData())
- 将缓冲区对象分配给attribute变量(gl.vertexAttribPointer())
- 开启attribute变量(gl.enableVertexAttribArray())
但是为了节省空间,两个不同的着色器是使用相同的顶点缓冲区数据,在需要的时候切换分配数据。因此这里可以将以上五步分成两个函数——在初始化的时候,进行1~3步:向顶点缓冲区写入数据,留待绘制的时候分配使用:
//向顶点缓冲区写入数据,留待以后分配
function initArrayBufferForLaterUse(gl, data, num, type) {// Create a buffer objectvar buffer = gl.createBuffer();if (!buffer) {console.log('Failed to create the buffer object');return null;}// Write date into the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, buffer);gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);// Store the necessary information to assign the object to the attribute variable laterbuffer.num = num;buffer.type = type;return buffer;
}
在绘制时切换到对应的着色器,进行4~5步:分配缓冲区对象并开启连接:
//分配缓冲区对象并开启连接
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);
}
当然,顶点数据索引也同时分配到顶点缓冲区,需要的时候绑定缓冲区对象即可:
//向顶点缓冲区写入索引,留待以后分配
function initElementArrayBufferForLaterUse(gl, data, type) {// Create a buffer objectvar buffer = gl.createBuffer();if (!buffer) {console.log('Failed to create the buffer object');return null;}// Write date into the buffer objectgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW);buffer.type = type;return buffer;
}
2.2.2. 帧缓冲区
帧缓冲区对象保存的是渲染的中间结果,因此分别存在三个关联对象——颜色关联对象(color attachment)、深度关联对象(depth attachment)和模板关联对象(stencil attachment),用来代替颜色缓冲区、深度缓冲区和模板缓冲区。关联对象分为两种:纹理对象和渲染缓冲区对象(renderbuffer object)。一般来说,可以定义一个纹理对象作为帧缓冲区的的颜色关联对象,定义一个渲染缓冲区对象作为帧缓冲区的深度关联对象,来实现离屏绘制。
在函数initFramebufferObject()中进行了帧缓冲区的初始化工作。具体来说, 帧缓冲区的具体设置过程可以分为如下8步:
2.2.2.1. 创建帧缓冲对象(gl.createFramebuffer())
通过gl.createFramebuffer()来创建初始化对象:
// 初始化帧缓冲区对象 (FBO)
function initFramebufferObject(gl) {//...// 创建帧缓冲区对象 (FBO)framebuffer = gl.createFramebuffer();if (!framebuffer) {console.log('Failed to create frame buffer object');return error();}//...
}
2.2.2.2. 创建纹理对象并设置其尺寸和参数
在教程《WebGL简易教程(十一):纹理》中就已经介绍过如何创建纹理对象并设置纹理对象的参数。这里的创建过程也是一样的;只是细节略有不同:
- 这里设置纹理的长、宽可以跟画布的长宽不一样,想要速度快,可以小一点;想要效果好,就可以大一点。
- gl.texImage2D函数的最后一个参数需设置为null,表示新建了一块空白的区域,以便帧缓存绘制。
function initFramebufferObject(gl) {//...// 创建纹理对象并设置其尺寸和参数texture = gl.createTexture(); // 创建纹理对象if (!texture) {console.log('Failed to create texture object');return error();}gl.bindTexture(gl.TEXTURE_2D, texture); // Bind the object to targetgl.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);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);framebuffer.texture = texture; // 保存纹理对象//...
}
2.2.2.3. 创建渲染缓冲区对象(gl.createRenderbuffer())
通过函数gl.createRenderbuffer()创建渲染缓冲区对象,这个渲染缓冲区对象将被指定成深度关联对象。
function initFramebufferObject(gl) {//...// 创建渲染缓冲区对象并设置其尺寸和参数depthBuffer = gl.createRenderbuffer(); //创建渲染缓冲区if (!depthBuffer) {console.log('Failed to create renderbuffer object');return error();}//...
}
2.2.2.4. 绑定渲染缓冲区并设置尺寸(gl.bindRenderbuffer(),gl.renderbufferStorage())
将渲染缓冲区绑定到目标上,通过目标设置渲染缓冲区的尺寸等参数。
function initFramebufferObject(gl) {//...gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); // Bind the object to targetgl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT);//...
}
对于WebGL/OpenGL而言,任何缓冲区对象都是需要绑定到目标上,再对目标进行操作的。绑定函数gl.bindRenderbuffer()的定义为:
绑定完成后,通过gl.renderbufferStorage()函数设置渲染缓冲区的格式、宽度以及高度等。注意深度关联的渲染缓冲区,其宽度和高度必须与作为颜色关联对象的纹理缓冲区一致。其函数定义为:
2.2.2.5. 将纹理对象关联到帧缓冲区对象(gl.bindFramebuffer(), gl.framebufferTexture2D)
仍然是先将帧缓冲绑定到目标上,使用函数gl.bindFramebuffer()进行绑定:
使用绑定的目标,将创建的纹理对象指定为帧缓冲区的颜色关联对象;函数gl.framebufferTexture2D()的定义如下:
实例中的相关代码如下:
function initFramebufferObject(gl) {//...// 将纹理和渲染缓冲区对象关联到帧缓冲区对象上gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); //关联颜色//...
}
注意这里的attachment参数的取值gl.COLOR_ATTACHMENT0,WebGL和OpenGL有所不同,WebGL只允许一个颜色关联对象而OpenGL允许多个。
2.2.2.6. 将渲染缓冲区对象关联到帧缓冲区对象(gl.framebufferRenderbuffer())
使用gl.framebufferRenderbuffer()函数将渲染缓冲区对象关联到帧缓冲区的深度关联对象:
function initFramebufferObject(gl) {//...gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer); //关联深度//...
}
其函数定义如下:
2.2.2.7. 检查帧缓冲区的配置(gl.checkFramebufferStatus())
配置帧缓冲区的过程很复杂,WebGL提供了检查函数gl.checkFramebufferStatus():
相关代码如下:
function initFramebufferObject(gl) {//...// 检查帧缓冲区是否被正确设置var e = gl.checkFramebufferStatus(gl.FRAMEBUFFER);if (gl.FRAMEBUFFER_COMPLETE !== e) {console.log('Frame buffer object is incomplete: ' + e.toString());return error();}//...
}
2.2.2.8. 在帧缓冲区进行绘制(gl.bindFramebuffer())
在需要在帧缓冲区绘制的时候调用绑定帧缓冲区对象,在需要在颜色缓冲区绘制的时候接触绑定。可以通过gl.bindFramebuffer()函数实现,具体可看下一节内容。
2.3. 绘制函数
初始化准备工作完成后,接下来在加载数据的后进行图形绘制操作,调用绘制函数DrawDEM():
demFile.addEventListener("change", function (event) {//...reader.onload = function () {if (reader.result) {//读取var terrain = new Terrain();if (!readDEMFile(reader.result, terrain)) {console.log("文件格式有误,不能读取该文件!");}//绘制DrawDEM(gl, canvas, fbo, frameProgram, drawProgram, terrain);}}
readDEMFile()是读取解析DEM文件的函数,并保存到自定义的Terrain对象中,通过这个Terrain对象,调用DrawDEM()进行绘制:
//绘制
function DrawDEM(gl, canvas, fbo, frameProgram, drawProgram, terrain) {// 设置顶点位置var demBufferObject = initVertexBuffersForDrawDEM(gl, terrain);if (!demBufferObject) {console.log('Failed to set the positions of the vertices');return;}//获取光线:平行光var lightDirection = getLight();//预先给着色器传递一些不变的量{//使用帧缓冲区着色器gl.useProgram(frameProgram);//设置MVP矩阵setMVPMatrix(gl, canvas, terrain.sphere, lightDirection, frameProgram);//使用颜色缓冲区着色器gl.useProgram(drawProgram);//设置MVP矩阵setMVPMatrix(gl, canvas, terrain.sphere, lightDirection, drawProgram);//将绘制在帧缓冲区的纹理传递给颜色缓冲区着色器的0号纹理单元gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, fbo.texture);gl.uniform1i(drawProgram.u_Sampler, 0);gl.useProgram(null);}//开始绘制var tick = function () {//帧缓存绘制gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); //将绘制目标切换为帧缓冲区对象FBOgl.viewport(0, 0, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT); // 为FBO设置一个视口gl.clearColor(0.2, 0.2, 0.4, 1.0); // Set clear color (the color is slightly changed)gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Clear FBOgl.useProgram(frameProgram); //准备生成纹理贴图//分配缓冲区对象并开启连接initAttributeVariable(gl, frameProgram.a_Position, demBufferObject.vertexBuffer); // 顶点坐标initAttributeVariable(gl, frameProgram.a_Color, demBufferObject.colorBuffer); // 颜色//分配索引并绘制gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, demBufferObject.indexBuffer);gl.drawElements(gl.TRIANGLES, demBufferObject.numIndices, demBufferObject.indexBuffer.type, 0);//颜色缓存绘制gl.bindFramebuffer(gl.FRAMEBUFFER, null); //将绘制目标切换为颜色缓冲区gl.viewport(0, 0, canvas.width, canvas.height); // 设置视口为当前画布的大小gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Clear the color buffergl.useProgram(drawProgram); // 准备进行绘制//分配缓冲区对象并开启连接initAttributeVariable(gl, drawProgram.a_Position, demBufferObject.vertexBuffer); // Vertex coordinat//分配索引并绘制gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, demBufferObject.indexBuffer);gl.drawElements(gl.TRIANGLES, demBufferObject.numIndices, demBufferObject.indexBuffer.type, 0);window.requestAnimationFrame(tick, canvas);};tick();
}
2.3.1. 初始化顶点数组
首先第一步仍然是初始化顶点缓冲区数组,但是与之前不同的是这个只传输顶点数据到顶点缓冲区,并不连接顶点着色器,因为两组着色器是公用顶点数据的,所以需要在切换着色器的时候分配着色器并连接:
function initVertexBuffersForDrawDEM(gl, terrain) {//DEM的一个网格是由两个三角形组成的// 0------1 1// | |// | |// col col------col+1 var col = terrain.col;var row = terrain.row;var indices = new Uint16Array((row - 1) * (col - 1) * 6);var ci = 0;for (var yi = 0; yi < row - 1; yi++) {//for (var yi = 0; yi < 10; yi++) {for (var xi = 0; xi < col - 1; xi++) {indices[ci * 6] = yi * col + xi;indices[ci * 6 + 1] = (yi + 1) * col + xi;indices[ci * 6 + 2] = yi * col + xi + 1;indices[ci * 6 + 3] = (yi + 1) * col + xi;indices[ci * 6 + 4] = (yi + 1) * col + xi + 1;indices[ci * 6 + 5] = yi * col + xi + 1;ci++;}}var dem = new Object(); // Create the "Object" object to return multiple objects.// Write vertex information to buffer objectdem.vertexBuffer = initArrayBufferForLaterUse(gl, terrain.vertices, 3, gl.FLOAT);dem.colorBuffer = initArrayBufferForLaterUse(gl, terrain.colors, 3, gl.FLOAT);dem.normalBuffer = initArrayBufferForLaterUse(gl, terrain.normals, 3, gl.FLOAT);dem.indexBuffer = initElementArrayBufferForLaterUse(gl, indices, gl.UNSIGNED_SHORT);if (!dem.vertexBuffer || !dem.colorBuffer || !dem.indexBuffer || !dem.normalBuffer) {return null;}dem.numIndices = indices.length;// Unbind the buffer objectgl.bindBuffer(gl.ARRAY_BUFFER, null);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);return dem;
}
2.3.2. 传递非公用随帧不变的数据
为了满足交互需求,绘制函数仍然是通过刷新页面函数requestAnimationFrame()实现的,有的数据是固定随帧不变的,这样的数据可以提前传输好。当然,这些数据不包含共用的顶点缓冲区数据:
//获取光线:平行光var lightDirection = getLight();//预先给着色器传递一些不变的量{//使用帧缓冲区着色器gl.useProgram(frameProgram);//设置MVP矩阵setMVPMatrix(gl, canvas, terrain.sphere, lightDirection, frameProgram);//使用颜色缓冲区着色器gl.useProgram(drawProgram);//设置MVP矩阵setMVPMatrix(gl, canvas, terrain.sphere, lightDirection, drawProgram);//将绘制在帧缓冲区的纹理传递给颜色缓冲区着色器的0号纹理单元gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, fbo.texture);gl.uniform1i(drawProgram.u_Sampler, 0);gl.useProgram(null);}
注意这里通过函数gl.useProgram()切换了着色器,然后再分别给着色器传输数据。在这个例子只是通过帧缓冲区做颜色中转,所以帧缓冲区和颜色缓冲区绘制的MVP矩阵是相同且固定的,所以可以提前传输好。并且,将帧缓冲区关联着颜色关联对象的纹理对象,分配给颜色缓冲区的片元着色器。
2.3.3. 逐帧绘制
刷新页面函数requestAnimationFrame()的回调函数tick()中进行绘制,页面每隔一段时间就会调用这个绘制函数。
2.3.3.1. 绘制到帧缓存
为了声明当前是绘制到帧缓存的,首先将要绑定帧缓冲区对象gl.bindFramebuffer()。然后调用gl.viewport()函数定义一个绘图的视口:
接下来还是通过gl.useProgram()切换到对应的着色器,分配并连接顶点缓冲区的顶点数据;最后调用gl.drawElements()进行绘制即可。
相关的代码如下:
//开始绘制var tick = function () {//帧缓存绘制gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); //将绘制目标切换为帧缓冲区对象FBOgl.viewport(0, 0, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT); // 为FBO设置一个视口gl.clearColor(0.2, 0.2, 0.4, 1.0); // Set clear color (the color is slightly changed)gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Clear FBOgl.useProgram(frameProgram); //准备生成纹理贴图//分配缓冲区对象并开启连接initAttributeVariable(gl, frameProgram.a_Position, demBufferObject.vertexBuffer); // 顶点坐标initAttributeVariable(gl, frameProgram.a_Color, demBufferObject.colorBuffer); // 颜色//分配索引并绘制gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, demBufferObject.indexBuffer);gl.drawElements(gl.TRIANGLES, demBufferObject.numIndices, demBufferObject.indexBuffer.type, 0);//...window.requestAnimationFrame(tick, canvas);};tick();
}
2.3.3.2. 绘制到颜色缓存
绘制到颜色缓冲区的步骤也是一致的,只不过在绘制之前需要调用gl.bindFramebuffer(gl.FRAMEBUFFER, null)解除帧缓冲区绑定,将绘制目标切换到当前的颜色缓冲区。当然,设置视口和切换着色器操作都是必须的。相关代码如下:
//开始绘制var tick = function () {//...//颜色缓存绘制gl.bindFramebuffer(gl.FRAMEBUFFER, null); //将绘制目标切换为颜色缓冲区gl.viewport(0, 0, canvas.width, canvas.height); // 设置视口为当前画布的大小gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Clear the color buffergl.useProgram(drawProgram); // 准备进行绘制//分配缓冲区对象并开启连接initAttributeVariable(gl, drawProgram.a_Position, demBufferObject.vertexBuffer); // Vertex coordinat//分配索引并绘制gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, demBufferObject.indexBuffer);gl.drawElements(gl.TRIANGLES, demBufferObject.numIndices, demBufferObject.indexBuffer.type, 0);window.requestAnimationFrame(tick, canvas);};tick();
}
3. 结果
最后运行的结果如下,显示的是一个特定角度的地形:
跟之前教程相比,示例似乎没有特别的地方。这个示例的关键点在于这个渲染效果经过了帧缓冲区的中转,给更深入的技术做准备——比如,下一篇要论述的技术:阴影。
4. 参考
本来部分代码和插图来自《WebGL编程指南》,源代码链接:地址 。会在此共享目录中持续更新后续的内容。
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- c3p0配置解析
1、C3P0与JDBC的相关概念 Connection:是指JDBC规范中的Connection,与接口java.sql.Connection相对应。与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果,一个Connection代表一个 物理数据库连接。 PhysicalConnection:物理连接,真正完成数据库与应用之…...
2024/4/17 19:19:23 - 利用Vulnhub复现漏洞 - Joomla 3.7.0 (CVE-2017-8917) SQL注入漏洞环境
@[TOC](Joomla 3.7.0 (CVE-2017-8917) SQL注入漏洞环境) Vulnhub官方复现教程 https://vulhub.org/#/environments/joomla/CVE-2017-8917/ 漏洞原理 com_fields组件出现漏洞,com_fields组件是在3.7版本添加的,如果你使用此版本,将受到影响,并应尽快更新。这个组件可以公开访…...
2024/4/20 12:22:37 - BeanShell使用标准Java语法
BeanShell 最重要的一点就是它是一个 Java 解释器。所以你可能已经知道使用 BeanShell 写脚本所需要的内容。本节着重介绍 BeanShell “认识”哪部分 Java 语言以及 BeanShell 如何扩展或者“松散”自己来变得类似于更多的脚本语言。 在 BeanShell 脚本(命令行)中,你可以敲打…...
2024/4/11 20:51:31 - 未能加载文件或程序集“Oracle.DataAccess, Version=2.112.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342”或它
未能加载文件或程序集“Oracle.DataAccess, Version=2.112.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342”或它的某一个依赖项。系统找不到指定的文件。运行代码时出现这个问题,原来是缺少文件的安装安装完这个文件,就OK了。。。。。。...
2024/4/17 19:21:11 - [WebGL入门]二十八,纹理参数
注:文章译自http://wgld.org/,原作者杉本雅広(doxas)本次demo的效果lufy:先啰嗦几句,真是好几年没写博客了,以后的工作要重新接触HTML5开发了,虽然没有以前那样强烈的写文章的欲望了,但是看了看以前的WebGL的教程只翻译了一小半,这么好的教程,就这么断更了也实在可惜,…...
2024/4/17 19:20:12 - 牛逼哄哄的 "零拷贝" 是什么?
作者:ksfzhaohuijuejin.im/post/5cad6f1ef265da039f0ef5df前言从字面意思理解就是数据不需要来回的拷贝,大大提升了系统的性能;这个词我们也经常在java nio,netty,kafka,RocketMQ等框架中听到,经常作为其提升性能的一大亮点;下面从I/O的几个概念开始,进而在分析零拷贝…...
2024/4/17 19:19:36 - 梳理STM32F429之通信传输部分---NO.4 RS232 通讯
目录一、RS232简介二、RS-232特点三、RS232接口串口Usart、COM口、TTL、RS-232的区别详解一、RS232简介在最初的应用中, RS-232 串口标准常用于计算机、路由与调制调解器(MODEN,俗称“猫” )之间的通讯 ,在这种通讯系统中,设备被分为数据终端设备 DTE(计算机、路由)和数据通…...
2024/4/20 13:52:04 - BeanShell Timer
目录1、使用场景2、相关参数1、使用场景:用BeanShell脚本语言来访问及设置JMeter的属性,访问及设置变量,还可用来记录日志。如用BeanShell来设置线程延迟间隔。2、相关参数Reset Interpreter:每次迭代是否重置解析器,默认为false;在长时间运行的脚本中建议设置为true。Pa…...
2024/5/10 4:58:32 - sql注入漏洞类型分类
1、(基于错误的get单引号字符型注)id=$id2、(基于错误的get整型注入)id=id3、(基于错误的get单引号变形字符型注入)id=($id)4、(基于错误的GET双引号字符型注入)id=("$id")5、盲注单引号字符型注入5、盲注双引号字符型注入...
2024/4/17 19:20:12 - 使用WebGL + Three.js制作动画场景
使用WebGL + Three.js制作动画场景3D图像,技术,打造产品,还有互联网:这些只是我爱好的一小部分。 现在,感谢WebGL的出现-一个新的JavaScriptAPI,它可以在不依赖任何插件的情况下渲染浏览器中的3D图像-这让3D渲染操作变得异常简单。 随着虚拟现实和增强现实应用的发展,…...
2024/4/17 19:20:23 - 现代控制理论(机器人方向)习题与实践补充资料和复习说明(2019版)
现代控制理论(机器人方向)习题与实践补充资料和复习说明(2019版)现代控制理论正确打开方式是怎样的?机器人/控制/学习/人工智能(OpenAI)课程已经接近尾声(2学分-32学时),现代控制系统理论内容分为:系统定量分析-状态空间描述及其解系统定性分析-能控能观和稳定性系统…...
2024/4/20 9:41:30 - CodeForces 429D Tricky Function
题目大意给出一个长度为N的序列a。 定义 f(i,j)=(i−j)2+g(i,j)2 g(i,j)=∑jk=iak 求最小的f(i,j)Data Constraint N≤105题解设Sum[i]表示1~i的和。 那么f(i,j)=(i−j)2+(Sum[j]−Sum[i])2 问题变成:求形如(i,Sum[i])点对间的最小距离。 可以分治求解。 时间复杂度:…...
2024/4/17 19:20:23 - c3p0 参数解释
acquireIncrement #当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3acquireRetryAttempts #定义在从数据库获取新连接失败后重复尝试的次数。Default: 30acquireRetryDelay #两次连接中间隔时间,单位毫秒。Default: 1000autoCommitOnClose #连接关闭时默认将…...
2024/4/12 23:03:27 - Mybatis框架下SQL注入漏洞书目录
Mybatis框架下SQL注入漏洞SQL注入漏洞基本原理Mybatis框架介绍Mybatis框架下易产生SQL注入漏洞场景分析Mybatis框架下SQL注入漏洞修复建议...
2024/4/17 19:20:23 - CVPR 2020学术竞赛大盘点,中国团队揽获众多冠军
2020-06-23 03:20:03作者 | 蒋宝尚编辑 | 丛 末CVPR 2020已经落下帷幕,除了为期三天的主会议,还穿插着同为期三天的Workshop,这些研讨会有一些是讨论性质的,还有一些是竞赛相关的。这些竞赛涉及了图像分类,超分辨率、图像视频压缩、图表检索与分析、低功耗计算机视觉等等领…...
2024/4/17 19:20:05 - Jmeter Ant Task如何让beanshell断言失败的详细信息展示在report里面
首先必须给beanshell断言添加FailureMessage if(${TotalClient_SS}+2!=${TotalClient_SS2}){Failure=true; FailureMessage="TotalClient_SS=${TotalClient_SS},TotalClient_SS2=${TotalClient_SS2},Expected:TotalClient_SS+2==TotalClient_SS2,Actually:${TotalCl…...
2024/4/17 19:21:42 - stm32f429的u-boot、uclinux内核烧写说明
最近比较忙,针对前面的留言说有怎么download u-boot、uclinux到stm32,我翻了翻以前记录下的笔记,特意贴上来,其实有些步骤我都已经忘记了。。。一、搭建嵌入式linux开发环境 1. 准备一台Linux系统(Fedora,CentOS,Ubuntu等)的电脑,将BSP压缩包(linux-cortexm-2.0.0.tar…...
2024/4/17 19:20:05 - WebGL自学教程——WebGL示例:悲摧了,浏览器升级后,有些功能我的本本的显卡不支持了
如题...
2024/4/17 22:43:48 - 硬核!如何模拟 5w+ 的并发用户?
来自:http://t.cn/ES7KBkW本文将从负载测试的角度,描述了做一次流畅的5万用户并发测试需要做的事情。你可以在本文的结尾部分看到讨论的记录.快速的步骤概要编写你的脚本使用JMeter进行本地测试BlazeMeter沙箱测试使用一个控制台和一个引擎设置Users-per-Engine的数量设置并测…...
2024/4/19 1:49:44 - 网站sql注入漏洞修复
String username = request.getParameter("f_username"); String inj_str = "|and|exec|insert|select|delete|update|count|*|%|chr|mid|master(www.111cn.net)|truncate|char|declare|;|or|-|+|,";//这里的东西还可以自己添加 String[] inj_stra=inj_str…...
2024/4/19 14:07:09
最新文章
- This error originates from a subprocess, and is likely not a problem with pip.
Preparing metadata (setup.py) ... errorerror: subprocess-exited-with-error python setup.py egg_info did not run successfully.│ exit code: 1╰─> [63 lines of output]WARNING: The repository located at mirrors.aliyun.com is not a trusted or secure host a…...
2024/5/10 6:08:18 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/5/9 21:23:04 - 游戏引擎架构01__引擎架构图
根据游戏引擎架构预设的引擎架构来构建运行时引擎架构 ...
2024/5/9 13:32:56 - 16个Python接单平台,做私活爽歪歪!(附100个爬虫源码)
一、python爬虫是可以做副业的,主要是爬取网站、小程序或者APP的数据,对数据进行分析与处理,或者直接向客户提供爬虫程序与技术支持。 当初学会Python那会儿,有朋友来介绍我去接私活,是为一家公司做网站,那…...
2024/5/10 0:14:51 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/8 6:01:22 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/9 15:10:32 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/5/4 23:54:56 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/9 4:20:59 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/5/4 23:54:56 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/5/4 23:55:05 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/5/4 23:54:56 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/5/7 11:36:39 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/5/4 23:54:56 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/6 1:40:42 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/5/4 23:54:56 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/5/8 20:48:49 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/5/7 9:26:26 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/5/4 23:54:56 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/8 19:33:07 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/5 8:13:33 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/5/8 20:38:49 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/5/4 23:54:58 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/9 7:32:17 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/5/9 17:11:10 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57