我正在尝试使用阴影贴图实现阴影,因此需要将场景渲染到单独的帧缓冲区(纹理)。我无法使它正常工作,所以在剥离代码库后,我只剩下一组相对简单的指令,这些指令应该将场景渲染为纹理,然后简单地渲染纹理。
该程序由两个程序组成:
- 地面计划
- 茶壶程序
第一个应该渲染一个具有特定纹理的矩形。第二个应该渲染茶壶(根据其位置使用颜色)。Eech渲染步骤执行以下操作(好吧,无论如何这就是想法):
- 切换到帧缓冲区
- 渲染茶壶
- 切换到正常缓冲区
- 渲染茶壶
- 渲染地面
现在,地面碎片着色器看起来像:
gl_FragColor=纹理2D(shadowMap,fTexCoord);
“shadowMap”是我在步骤2中渲染到的纹理。我期待看到一个漂浮的茶壶,下面画着一个长方形。这确实有效。现在,我还希望有一个“地面”来容纳茶壶。毕竟,我们渲染了我们正在查看的场景,而没有将地面渲染到帧缓冲区/纹理。
代码
var UNSIGNED_SHORT_SIZE=2;//setup()填充的变量var glCanvas;var gl,茶壶程序,地面程序;var vBuffer、iBuffer和fBuffer;var顶点、索引、纹理;var茶壶=空;var模型;var视图;var光;var投影;var BASE_URL=“https://hmbastiaan.nl/martijn/webgl/W08P02_SO/";var宽度=150,高度=150;函数makeTeapot(){var drawingInfo=茶壶.getDrawingInfoObjects();var指数=drawingInfo.indices;for(var i=0;i<指数.length;i++){指数[i]+=4;//为“地面”添加偏移}返回{索引:drawingInfo.indices,顶点:drawingInfo.vertices}}函数makeRectangle(x1,x2,y1,y2,z1,z2){var x1=-2,x2=2,y1=-1,y2=-1,z1=-1,z2=-5;var顶点=[vec4(x1,y2,z1,1),vec4(x2,y1,z1,1),vec4(x2,y1,z2,1),vec4(x1,y2,z2,1)];var纹理=[vec2(-1.0,-1.0),vec2(1.0,-1.0),vec2(1.0,1.0),vec2(-1.0,1.0)];var指数=[0, 1, 2,0, 2, 3];返回{索引:索引,顶点:顶点,纹理:纹理}}函数resetBuffers(){顶点=[];指数=[];纹理=[];//添加矩形var矩形=makeRectangle();Array.prototype.push.apply(顶点、矩形顶点);数组.原型.推送.应用(索引,矩形.索引);数组.原型.推送.应用(纹理,矩形.纹理);//添加茶壶var茶壶=制作茶壶();数组.原型.推送.应用(顶点,茶壶.顶点);数组.原型.推送.应用(索引,茶壶.索引);console.log(顶点);console.log(索引);console.log(纹理);//发送到GPUgl.bindBuffer(gl.ARRAY_BUFFER,vBuffer);gl.bufferData(gl.ARRAY_BUFFER,展平(顶点),gl.STATIC_DRAW);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,iBuffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,新Uint16Array(索引),gl.STATIC_DRAW);}函数设置(){$.get(BASE_URL+“teapot.obj”,函数(teapot_obj_data){teapot=新OBJDoc(BASE_URL+“teapot.obj”);if(!teapot.parse(teapotobj_data,1)){alert(“分析teapot.obj失败。”);回报;}设置2();}).fail(函数(){alert(“获取teapot.obj失败。”);});}函数设置2(){glCanvas=文档.getElementById(“gl-canvas”);gl=WebGLUtils.setupWebGL(glCanvas,{stencil:true,alpha:false});gl.视口(0,0,宽度,高度);teapotProgram=initShaders(gl,BASE_URL+“vshader-teapot.glsl”,BASE_FRL+“fshader-tapot.glsl”);groundProgram=initShaders(gl,BASE_URL+“vshader-ground.glsl”,BASE_FRL+“fshader-geround.gsl”);灯光=vec3(0.0、2.0、-2.0);视图=lookAt(vec3(0,0,3),vec3;投影=透视(45,1.0,1100.0);//拿茶壶制服gl.useProgram(teapotProgram);teapotProgram.modelLoc=gl.getUniformLocation(茶壶程序,“模型”);teapotProgram.viewLoc=gl.getUniformLocation(茶壶程序,“视图”);teapotProgram.projectionLoc=gl.getUniformLocation(茶壶程序,“投影”);//上传制服gl.uniformMatrix4fv(teapotProgram.projectionLoc,false,扁平(投影));gl.uniformMatrix4fv(teapotProgram.viewLoc,false,扁平(view));gl.uniformMatrix4fv(teapotProgram.modelLoc,false,扁平(缩放(0.25,0.25,0.25));//获取茶壶属性teapotProgram.vPosition=gl.getAttribLocation(teapot程序,“vPosition”);//获取地面制服gl.useProgram(地面程序);groundProgram.modelLoc=gl.getUniformLocation(groundProgram,“模型”);groundProgram.viewLoc=gl.getUniformLocation(地面程序,“视图”);groundProgram.projectionLoc=gl.getUniformLocation(地面程序,“投影”);groundProgram.shadowMap=gl.getUniformLocation(groundProgram,“shadowMap”);//获取地面属性地面程序.vTexCoord=gl.getAttribLocation(地面程序,“vTexCourd”);groundProgram.vPosition=gl.getAttribLocation(groundProgram,“vPosition”);//分配和填充顶点缓冲区vBuffer=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,vBuffer);gl.vertexAttribPointer(teapotProgram.vPosition,4,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(teapotProgram.vPosition);gl.vertexAttribPointer(groundProgram.vPosition,4,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(groundProgram.vPosition);//分配索引缓冲区iBuffer=gl.createBuffer();//设置固定基地运营商fBuffer=gl.createFramebuffer();gl.bindFramebuffer(gl.FRAMEBUFFER,fBuffer);fBuffer.renderbuffer=gl.createRenderbuffer();gl.bindRenderbuffer(gl.RENDERBUFFER,fBuffer.RENDERBUFFER);gl.渲染缓冲存储(gl.RENDERBUFFER,gl.DEPTH_COMPONENT16,512,512);fBuffer.texture=gl.createTexture();gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,fBuffer.TEXTURE);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,512512,0,gl.RGBA,gl.UNSIGNED_BYTE,空);gl.生成位图(gl.TEXTURE_2D);gl.tex参数(gl.TEXTURE_2D,gl.TESTURE_MIN_FILTER,gl.NEAREST_MIMPAP_LINEAR);gl.tex参数(gl.TEXTURE_2D,gl.TESTURE_MAG_FILTER,gl.NEAREST);gl.帧缓冲区纹理2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,fBuffer.TEXTURE,0);gl.帧缓冲渲染缓冲区(gl.FRAMEBUFFER、gl.DEPTH_ATTACHMENT、gl.RENDERBUFFER和fBuffer.RENDERBUFFER);//健全性检查:帧缓冲区现在似乎抛出错误if(!gl.is帧缓冲区(fBuffer)){throw(“无效帧缓冲区”);}var status=gl.checkFramebufferStatus(gl.FRAMEBUFFER);开关(状态){案例gl.FRAMEBUFFER_COMPLETE:断裂;案例gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:throw(“不完整的帧缓冲区:framebuffer_Incomplete_ATTACHMENT”);断裂;案例gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:throw(“不完整的帧缓冲区:framebuffer_Incomplete_MISSING_ATTACHMENT”);断裂;案例gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:throw(“不完整的帧缓冲区:framebuffer_Incomplete_DIMENSIONS”);断裂;案例gl.FRAMEBUFFER_UNSUPPORTED:throw(“不完整的帧缓冲区:framebuffer_UNSUPPORTED”);断裂;违约:throw(“帧缓冲区不完整:”+状态);}//设置地面纹理gl.uniform1i(groundProgram.shadowMap,0);//上传制服gl.uniformMatrix4fv(groundProgram.projectionLoc,false,扁平(投影));gl.uniformMatrix4fv(groundProgram.viewLoc,false,扁平(view));gl.uniformMatrix4fv(groundProgram.modelLoc,false,扁平(mat4()));//恢复默认缓冲区gl.bindTexture(gl.TEXTURE_2D,null);gl.bindRenderbuffer(gl.RENDERBUFFER,null);gl.bindFramebuffer(gl.FRAMEBUFFER,null);//设置背景颜色gl.透明色(0.3921,0.5843,0.9294,1.0);全局启用(全局深度测试);全局启用(全局CULL_FACE);resetBuffers();window.requestAnimationFrame(渲染);}函数render(){var茶壶=制作茶壶();gl.useProgram(teapotProgram);gl.清除(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFFER_BIT| gl.STENCIL_BUFFER _BIT);//切换到帧缓冲区gl.bindFramebuffer(gl.FRAMEBUFFER,fBuffer);//绘制茶壶茶壶=制作茶壶();gl.drawElements(gl.TRIANGLES,teapot.indices.length,gl.UNSIGNED_SHORT,6*UNSIGNED_SHORT_SIZE);//将帧缓冲区设置为消除缓冲区(浏览器内输出)gl.bindFramebuffer(gl.FRAMEBUFFER,null);//绘制地面gl.useProgram(地面程序);gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);//渲染茶壶gl.useProgram(teapotProgram);gl.drawElements(gl.TRIANGLES,teapot.indices.length,gl.UNSIGNED_SHORT,6*UNSIGNED_SHORT_SIZE);}设置();
<div><br/>抱歉:|</cavas></div><script type='text/javascript'src=“https://code.jquery.com/jquery-2.1.4.min.js“></script><script type='text/javascript'src=“https://hmbastiaan.nl/martijn/webgl/angel/webgl-utils.js“></script><script type='text/javascript'src=“https://hmbastiaan.nl/martijn/webgl/angel/initShaders2.js“></script><script type='text/javascript'src=“https://hmbastian.nl/martijn/webgl/angel/MV.js“></script><script type='text/javascript'src=“https://hmbastiaan.nl/martijn/webgl/angel/objParser.js“></script>
感兴趣的功能:
- setup2():设置所有缓冲区和制服。
- render():渲染场景。
免责声明:这是一个赋值,尽管此代码已简化到与原始赋值完全不同:)。