中心凹渲染:WebGL可以从屏幕中心向外螺旋渲染顶点/片段着色器吗?
如何告诉WebGL从屏幕中心渲染,然后按顺时针方向向外扩展,如果时间过长,如何取消/停止渲染中心凹渲染:WebGL可以从屏幕中心向外螺旋渲染顶点/片段着色器吗?,webgl,Webgl,如何告诉WebGL从屏幕中心渲染,然后按顺时针方向向外扩展,如果时间过长,如何取消/停止渲染 或者我需要自己手动平铺多张画布,并在所有画布上投影吗?作为我对您问题的评论示例,下面是一个过于简单的中心凹渲染示例。我从渲染到纹理的示例开始 那个 将带纹理的立方体渲染为纹理 将立方体的纹理渲染为画布上的立方体 这个 将纹理立方体渲染为低分辨率纹理 将带纹理的立方体渲染为高分辨率纹理 渲染填充画布的低分辨率纹理 渲染中心的高分辨率纹理 有很多瑕疵,低分辨率纹理的分辨率太低,你需要更好的算法来混合它们,但
或者我需要自己手动平铺多张画布,并在所有画布上投影吗?作为我对您问题的评论示例,下面是一个过于简单的中心凹渲染示例。我从渲染到纹理的示例开始 那个 将带纹理的立方体渲染为纹理 将立方体的纹理渲染为画布上的立方体 这个 将纹理立方体渲染为低分辨率纹理 将带纹理的立方体渲染为高分辨率纹理 渲染填充画布的低分辨率纹理 渲染中心的高分辨率纹理 有很多瑕疵,低分辨率纹理的分辨率太低,你需要更好的算法来混合它们,但它显示了效果 唯一不寻常的事情 将视口更改为仅渲染到中心。也可以通过缩放平面来实现这一点
// Tell WebGL how to convert from clip space to pixels
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
drawRenderTarget(lowResRT);
// Tell WebGL how to convert from clip space to pixels
gl.viewport(
gl.canvas.width / 4,
gl.canvas.height / 4,
gl.canvas.width / 2,
gl.canvas.height / 2);
drawRenderTarget(highResRT);
使用平截头体函数来计算平截头体,而不是更传统的透视函数。平截头体函数采用左、右、下、上、近、远参数,并计算一个投影矩阵,眼睛位于0、0,左、右、上、下描述眼睛前方的矩形。它比透视函数更灵活,因为它允许消失点位于任何位置,而不仅仅是中心
在这种情况下,该代码计算一个截头体的正确值,其中心和近平面的中心是2单位高和2×纵横单位宽。它计算一个子矩形,而不是。这就是我们如何使高分辨率纹理与低分辨率纹理匹配
// Compute the projection matrix
var near = 1;
// compute a near plane 2 units tall, 2 * aspect high
var vTop = near * Math.tan(fieldOfViewRadians * 0.5);
var vHeight = 2 * vTop;
var vWidth = aspect * vHeight;
var vLeft = -0.5 * vWidth;
// how compute a subrect of that near plane where
// left, bottom are offsets into the computed near plane
// and width, height are the dimensions of the sub rect
vLeft += left * vWidth / 2;
vTop -= bottom * vHeight / 2;
vWidth *= width / 2;
vHeight *= height / 2;
var projectionMatrix =
m4.frustum(vLeft, vLeft + vWidth, vTop - vHeight, vTop, near, 2000);
严格使用;
主要功能{
//获取WebGL上下文
/**@type{HTMLCanvasElement}*/
var canvas=document.getElementByIdcanvas;
var gl=canvas.getContextwebgl;
如果!德国劳埃德船级社{
回来
}
//安装GLSL程序
var program=webglUtils.createProgramFromScriptsgl,[3d顶点着色器,3d片段着色器];
//查找顶点数据需要去的地方。
var positionLocation=gl.GetAttriblLocationProgram,一个位置;
var texcoordLocation=gl.getAttribLocationprogram,a_texcoord;
//查找制服
var matrixLocation=gl.GetUniformLocation程序,u_矩阵;
var textureLocation=gl.getUniformLocationprogram,u_纹理;
//为位置创建缓冲区
var positionBuffer=gl.createBuffer;
//将其绑定到ARRAY\u BUFFER将其视为ARRAY\u BUFFER=positionBuffer
gl.bindbuffer gl.ARRAY_BUFFER,positionBuffer;
//把位置放在缓冲器里
setGeometrygl;
//为矩形提供纹理坐标。
var texcoordBuffer=gl.createBuffer;
gl.bindBuffergl.ARRAY_BUFFER,texcoordBuffer;
//设置Texcoords。
setTexcoordsgl;
//为位置创建缓冲区
var planePositionBuffer=gl.createBuffer;
//将其绑定到ARRAY\u BUFFER将其视为ARRAY\u BUFFER=positionBuffer
gl.bindbuffer gl.ARRAY_BUFFER,planePositionBuffer;
//把位置放在缓冲器里
gl.bufferDatagl.ARRAY\U缓冲区,新浮点数组[
-1, -1,
1, -1,
-1, 1,
-1, 1,
1, -1,
1, 1,
],gl.静态图;
//为矩形提供纹理坐标。
var planeTexcoordBuffer=gl.createBuffer;
gl.bindBuffergl.ARRAY_BUFFER,PlaneteCoordBuffer;
//设置Texcoords。
gl.bufferDatagl.ARRAY\U缓冲区,新浮点数组[
0, 0,
1, 0,
0, 1,
0, 1,
1, 0,
1, 1,
],gl.静态图;
//仅为立方体创建纹理。
var texture=gl.createTexture;
gl.bindTexturegl.TEXTURE_2D,纹理;
{
//使用3x2像素填充纹理
常数级=0;
const internalFormat=gl.亮度;
常数宽度=3;
常数高度=2;
常数边界=0;
常量格式=gl.亮度;
常量类型=gl.无符号字节;
常数数据=新的UINT8阵列[
128, 64, 128,
0, 192, 0,
];
常量对齐=1;
gl.pixelStoreigl.UNPACK_校准,校准;
gl.texImage2Dgl.TEXTURE_2D,级别,内部格式,宽度,高度,边框,
格式、类型、数据;
//设置筛选,这样我们就不需要mips,也不会对其进行筛选
gl.texParameterigl.TEXTURE_2D,gl.TEXTURE_MIN_过滤器,gl.NEAREST;
gl.texParameterigl.TEXTURE_2D,gl.TEXTURE_MAG_过滤器,gl.NEAREST;
gl.texParameterigl.TEXTURE_2D、gl.TEXTURE_WRAP_S、gl.CLAMP_TO_EDGE;
gl.texParameterigl.TEXTURE_2D、gl.TEXTURE_WRAP_T、gl.CLAMP_至边;
}
//创建要渲染到的纹理
函数CreateRenderTargetTargetTextRewidth,TargetTextReHeight{
const targetTexture=gl.createTexture;
gl.bindTexturegl.TEXTURE_2D,targetTexture;
{
//定义级别0的大小和格式
常数级=0;
const internalFormat=gl.RGBA;
常数边界=0;
常量格式=gl.RGBA;
常量类型=
gl.无符号字节;
const data=null;
gl.texImage2Dgl.TEXTURE_2D,级别,内部格式,
TargetTextRewidth、TargetTextReheight、border、,
格式、类型、数据;
//设置筛选,这样我们就不需要mips了
gl.texParameterigl.TEXTURE_2D,gl.TEXTURE_MIN_过滤器,gl.LINEAR;
gl.texParameterigl.TEXTURE_2D、gl.TEXTURE_WRAP_S、gl.CLAMP_TO_EDGE;
gl.texParameterigl.TEXTURE_2D、gl.TEXTURE_WRAP_T、gl.CLAMP_至边;
}
//创建并绑定帧缓冲区
const fb=gl.createFramebuffer;
gl.bindframebuffer gl.FRAMEBUFFER,fb;
//将纹理作为第一个颜色附着
const attachmentPoint=gl.COLOR\u ATTACHMENT0;
常数级=0;
gl.framebufferTexture2Dgl.FRAMEBUFFER,attachmentPoint,gl.TEXTURE_2D,targetTexture,level;
返回{
帧缓冲区:fb,
纹理:targetTexture,
宽度:targetTextRewidth,
高度:目标高度,
};
}
const lowResRT=createRenderTarget32,32;
const highResRT=createRenderTarget256,256;
函数degToRadd{
返回d*Math.PI/180;
}
var fieldOfViewRadians=degToRad60;
var ModelX旋转弧度=degToRad0;
var模型旋转弧度=degToRad0;
//获取开始时间。
var=0;
requestAnimationFramedrawScene;
函数drawCubeaspect,左侧,底部,宽度,高度{
//告诉它使用我们的程序对着色器
gl.useprogrammProgram;
//启用“位置”属性
gl.EnableVertexAttributeArrayPositionLocation;
//绑定位置缓冲区。
gl.bindbuffer gl.ARRAY_BUFFER,positionBuffer;
//告诉position属性如何从positionBuffer数组\u BUFFER中获取数据
var size=3;//每次迭代3个组件
var type=gl.FLOAT;//数据为32位浮点
var normalize=false;//不规范化数据
var stride=0;//0=向前移动大小*大小键入每个迭代以获得下一个位置
var offset=0;//从缓冲区的开头开始
gl.VertexAttribute指针
位置、位置、尺寸、类型、规格化、步幅、偏移;
//启用teccord属性
gl.EnableVertexAttributeArrayExcoordLocation;
//绑定位置缓冲区。
gl.bindBuffergl.ARRAY_BUFFER,texcoordBuffer;
//告诉position属性如何从positionBuffer数组\u BUFFER中获取数据
var size=2;//每次迭代2个组件
var type=gl.FLOAT;//数据为32位浮点
var normalize=false;//不规范化数据
var stride=0;//0=向前移动大小*大小键入每个迭代以获得下一个位置
var offset=0;//从缓冲区的开头开始
gl.VertexAttribute指针
texcoordLocation、大小、类型、规格化、跨步、偏移;
//计算投影矩阵
var近=1;
//计算一个近平面,2个单位高,2*纵横比高
var vTop=近*Math.tanfieldOfViewRadians*0.5;
var vHight=2*vTop;
var vWidth=宽高比*高高比;
var vLeft=-0.5*vWidth;
//如何计算平面附近的子矩形
//左下角是计算的近平面中的偏移
//和宽度、高度是子矩形的尺寸
vLeft+=左*宽/2;
vTop-=底部*vHight/2;
vWidth*=宽度/2;
vHeight*=高度/2;
向量投影矩阵=
m4.VrustumvLeft,vLeft+vWidth,vTop-vHeight,vTop,近,2000年;
var cameraPosition=[0,0,2];
var-up=[0,1,0];
var目标=[0,0,0];
//使用“查看”计算相机的矩阵。
var cameraMatrix=m4.lookAtcameraPosition,target,up;
//从摄影机矩阵创建视图矩阵。
var viewMatrix=m4.inversecameraMatrix;
var viewProjectionMatrix=m4.multipleProjectionMatrix,viewMatrix;
var矩阵=m4.x旋转视图投影矩阵,X型旋转弧度;
矩阵=m4.0旋转矩阵,模型旋转弧度;
//设定矩阵。
gl.UniformMatrix4FvMatrixlLocation,false,矩阵;
//告诉着色器对u_纹理使用纹理单元0
gl.uniform1,0;
//绘制几何图形。
gl.drawArraysgl.TRIANGLES,0,6*6;
}
功能方面{
//告诉它使用我们的程序对着色器
gl.useprogrammProgram;
//启用“位置”属性
gl.EnableVertexAttributeArrayPositionLocation;
//绑定位置缓冲区。
gl.bindbuffer gl.ARRAY_BUFFER,planePositionBuffer;
//告诉position属性如何从positionBuffer数组\u BUFFER中获取数据
var size=2;//每次迭代2个组件
var type=gl.FLOAT;//数据为32位浮点
var normalize=false;//不规范化数据
var stride=0;//0=向前移动大小*大小键入每个迭代以获得下一个位置
var offset=0;//从缓冲区的开头开始
gl.VertexAttribute指针
位置、位置、尺寸、类型、,
正常化、步幅、偏移;
//启用teccord属性
gl.EnableVertexAttributeArrayExcoordLocation;
//绑定位置缓冲区。
gl.bindBuffergl.ARRAY_BUFFER,PlaneteCoordBuffer;
//告诉position属性如何从positionBuffer数组\u BUFFER中获取数据
变量大小=2;//每次迭代2个组件
变量类型=gl.FLOAT;//数据是32位浮点数
var normalize=false;//不要规范化数据
var stride=0;//0=向前移动大小*大小键入每个迭代以获得下一个位置
变量偏移量=0;//从缓冲区的开头开始
gl.VertexAttribute指针
texcoordLocation、大小、类型、规格化、跨步、偏移;
//计算投影矩阵
var矩阵=m4.1;
//设定矩阵。
gl.UniformMatrix4FvMatrixlLocation,false,矩阵;
//告诉着色器对u_纹理使用纹理单元0
gl.uniform1,0;
//绘制几何图形。
gl.drawArraysgl.TRIANGLES,0,6;
}
//画场景。
函数drawScenetime{
//转换为秒
时间*=0.001;
//从当前时间中减去上一时间
var deltaTime=时间-然后;
//记住下一帧的当前时间。
然后=时间;
//为旋转设置动画
模型旋转弧度+=-0.7*deltaTime;
型号X旋转弧度+=-0.4*deltaTime;
webglUtils.resizeCanvasToDisplaySizegl.canvas;
gl.enablegl.CULL_面;
gl.enablegl.DEPTH_测试;
功能图UnderTargetRT,左侧,底部,宽度,高度{
//通过绑定帧缓冲区渲染到我们的targetTexture
gl.bindframebuffer gl.FRAMEBUFFER,rt.FRAMEBUFFER;
//使用我们的颜色纹理渲染立方体
gl.bindTexturegl.TEXTURE_2D,纹理;
//告诉WebGL如何将剪辑空间转换为像素
gl.viewport0,0,rt.width,rt.height;
//清除附件。
gl.clearColor0,0,1,1;//清除为蓝色
gl.cleargl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT;
const aspect=gl.canvas.clientWidth/gl.canvas.clientHeight;
drawCubeaspect,左侧,底部,宽度,高度;
}
drawToRenderTargetlowResRT,0,0,2,2;
drawToRenderTargethighResRT,0.5,0.5,1,1;
函数drawRenderTargetrt{
//渲染到画布
gl.bindframebuffer gl.FRAMEBUFFER,空;
//使用刚才渲染到的纹理渲染立方体
gl.bindTexturegl.TEXTURE_2D、rt.TEXTURE;
const aspect=gl.canvas.clientWidth/gl.canvas.clientHeight;
绘画方面;
}
gl.disablegl.DEPTH_测试;
//告诉WebGL如何将剪辑空间转换为像素
gl.viewport0,0,gl.canvas.width,gl.canvas.height;
drawRenderTargetlowResRT;
//告诉WebGL如何将剪辑空间转换为像素
总图视口
gl.canvas.width/4,
gl.canvas.height/4,
gl.canvas.width/2,
gl.canvas.height/2;
drawRenderTargethighResRT;
requestAnimationFramedrawScene;
}
}
//用定义多维数据集的值填充缓冲区。
函数集GeometryGL{
变量位置=新的浮动数组
[
-0.5, -0.5, -0.5,
-0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, 0.5, -0.5,
0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, -0.5,
0.5, -0.5, 0.5,
-0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, 0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, -0.5,
0.5, 0.5, 0.5,
];
gl.bufferDatagl.ARRAY_缓冲区、位置、gl.STATIC_绘图;
}
//使用立方体的纹理坐标填充缓冲区。
函数setTexcoordsgl{
缓冲数据
gl.ARRAY\u缓冲区,
新浮点数组
[
0, 0,
0, 1,
1, 0,
0, 1,
1, 1,
1, 0,
0, 0,
0, 1,
1, 0,
1, 0,
0, 1,
1, 1,
0, 0,
0, 1,
1, 0,
0, 1,
1, 1,
1, 0,
0, 0,
0, 1,
1, 0,
1, 0,
0, 1,
1, 1,
0, 0,
0, 1,
1, 0,
0, 1,
1, 1,
1, 0,
0, 0,
0, 1,
1, 0,
1, 0,
0, 1,
1, 1,
],
gl.静态绘制;
}
主要的
身体{
保证金:0;
}
帆布{
宽度:100vw;
高度:100vh;
显示:块;
}
属性向量4 a_位置;
属性向量2 a_texcoord;
均匀mat4u_矩阵;
可变矢量2 v_texcoord;
虚迈
n{
//将位置乘以矩阵。
gl_位置=u_矩阵*a_位置;
//将texcoord传递给片段着色器。
v_texcoord=a_texcoord;
}
精密中泵浮子;
//从顶点着色器传入。
可变矢量2 v_texcoord;
//纹理。
均匀的二维u_纹理;
真空总管{
gl_FragColor=纹理2 du_纹理,v_texcoord;
}
AFAICT大多数中心凹渲染都不是这样工作的。IIUC大多数中心凹渲染的工作原理是渲染不同分辨率的纹理,然后使用各种技术将它们组合在一起。好吧,格曼说的没错,中心凹渲染不是这样工作的。将画布平铺在一起会非常低效,因为您无法在始终绑定到单个画布的webgl上下文之间共享资源,更不用说您无法以这种方式使用WebVR API,因为这也假设了单个画布。