渲染到纹理

这节是重点,应该多写写。高级的渲染都要涉及到渲染到纹理。

在dx中,初始化设定surface和纹理后,每帧 setrendertarget,获得离屏纹理,然后传递给需要的物体。

同样,在webgl中,也是这样,

dx中的surface,在webgl称作帧缓冲区对象,后者分为颜色关联对象,深度关联对象和模板关联对象

dx中 的texture,在webgl中划分为两部分,纹理对象和渲染缓冲区对象。其中纹理对象对应颜色关联对象,即绘制颜色;渲染缓冲区对象是个控制消隐和模板的,即对应深度关联对象和模板关联对象。

 

步骤即:先创建对象,再关联对象绑定,再检查帧缓冲区是否正确配置,最后配置

具体如下:

1,创建帧缓冲区对象(gl.createFrameBuffer());

2,创建纹理对象并设置尺寸和参数(gl.createTexture(),gl.bindTexture(), gl.texImage2D(),gl.Parameteri()

3,创建渲染缓冲区对象(gl.createRenderBuffer())

4,绑定渲染缓冲区对象并设置其尺寸(gl.bindRenderBuffer(),gl.renderBufferStorage())

5,将帧缓冲区的颜色关联对象指定为一个纹理对象(gl.FrameBufferTexture2d())

6,将帧缓冲区的深度管理对象指定为一个渲染缓冲区对象(gl.framebufferRenderBuffer())

7,检查帧缓冲区是否正确配置(gl.checkFrameBufferStatus())

8,在帧缓冲区中进行绘制(gl.bindFrameBuffer())

代码如下:

<html>
<head>11</head>
<body>
<canvas id = "test" width = "800" height = "800">canvas </canvas>
<script src = "webgltest/cuon-matrix.js"></script>
<script >
//顶点着色器
var vertexShaderSource =
    'attribute vec4 a_Position;\n' +
    'attribute vec2 a_TexCoord;\n' +
    'uniform mat4 u_MvpMatrix;\n' +
    'varying vec2 v_TexCoord;\n'+
    'void main() {\n' +
    'gl_Position =  u_MvpMatrix * a_Position;\n'+       
    'v_TexCoord = a_TexCoord;\n' +
    '}\n';

//片元着色器
var fragmentShaderSource =
    'precision mediump float;\n' +
    'uniform sampler2D u_Sampler;\n' +
    'varying vec2 v_TexCoord;\n' +
    'void main() {\n' +       
    'gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n' +              //将数据传给片元着色器
    '}\n';
    
//离屏绘制尺寸
var OFFSCREEN_WIDTH = 256;
var OFFSCREEN_HEIGHT = 256;

//创建着色器方法,输入参数:渲染上下文,着色器类型,数据源
function createShader(gl, type, source)
{
    //创建着色器对象
    var shader = gl.createShader(type);
    //提供数据源
    gl.shaderSource(shader,source);
    //编译着色器
    gl.compileShader(shader);
    //链接
    var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
    if(success)
    {
        return shader;
    }
    console.log(gl.getShaderInfoLog(shader));
    gl.deleteShader(shader);
    
}
//将顶点着色器和像素着色器链接到一个着色程序
function createProgram(gl, vertexShader, fragmentShader)
{
    var program = gl.createProgram();
    gl.attachShader( program, vertexShader);
    gl.attachShader( program, fragmentShader);
    gl.linkProgram( program );
    var success = gl.getProgramParameter(program, gl.LINK_STATUS);
    if(success)
    {
        console.log("link right");
        return program;
    }
    console.log(gl.getProgramInfoLog(program));
    gl.deleteProgram(program);
}

//创建顶点缓冲区和索引缓冲区
function initVertexBuffersForCube(gl) {
  // Create a cube
  //    v6----- v5
  //   /|      /|
  //  v1------v0|
  //  | |     | |
  //  | |v7---|-|v4
  //  |/      |/
  //  v2------v3

  // Vertex coordinates
  var vertices = 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,    // v0-v1-v2-v3 front
     1.0, 1.0, 1.0,   1.0,-1.0, 1.0,   1.0,-1.0,-1.0,   1.0, 1.0,-1.0,    // v0-v3-v4-v5 right
     1.0, 1.0, 1.0,   1.0, 1.0,-1.0,  -1.0, 1.0,-1.0,  -1.0, 1.0, 1.0,    // v0-v5-v6-v1 up
    -1.0, 1.0, 1.0,  -1.0, 1.0,-1.0,  -1.0,-1.0,-1.0,  -1.0,-1.0, 1.0,    // v1-v6-v7-v2 left
    -1.0,-1.0,-1.0,   1.0,-1.0,-1.0,   1.0,-1.0, 1.0,  -1.0,-1.0, 1.0,    // v7-v4-v3-v2 down
     1.0,-1.0,-1.0,  -1.0,-1.0,-1.0,  -1.0, 1.0,-1.0,   1.0, 1.0,-1.0     // v4-v7-v6-v5 back
  ]);

  // Texture coordinates
  var texCoords = new Float32Array([
      1.0, 1.0,   0.0, 1.0,   0.0, 0.0,   1.0, 0.0,    // v0-v1-v2-v3 front
      0.0, 1.0,   0.0, 0.0,   1.0, 0.0,   1.0, 1.0,    // v0-v3-v4-v5 right
      1.0, 0.0,   1.0, 1.0,   0.0, 1.0,   0.0, 0.0,    // v0-v5-v6-v1 up
      1.0, 1.0,   0.0, 1.0,   0.0, 0.0,   1.0, 0.0,    // v1-v6-v7-v2 left
      0.0, 0.0,   1.0, 0.0,   1.0, 1.0,   0.0, 1.0,    // v7-v4-v3-v2 down
      0.0, 0.0,   1.0, 0.0,   1.0, 1.0,   0.0, 1.0     // v4-v7-v6-v5 back
  ]);

  // Indices of the vertices
  var indices = new Uint8Array([
     0, 1, 2,   0, 2, 3,    // front
     4, 5, 6,   4, 6, 7,    // right
     8, 9,10,   8,10,11,    // up
    12,13,14,  12,14,15,    // left
    16,17,18,  16,18,19,    // down
    20,21,22,  20,22,23     // back
  ]);
 
  var theObject = new Object();
  theObject.vertexBuffer = initArrayBufferForLateruse(gl, vertices, 3, gl.FLOAT);
  theObject.texcoordBuffer = initArrayBufferForLateruse(gl, texCoords, 2, gl.FLOAT);
  theObject.indexBuffer = initElementArrayBufferForLaterUse(gl, indices, gl.UNSIGNED_BYTE);
  if( !theObject.vertexBuffer || !theObject.texcoordBuffer || !theObject.indexBuffer)
  {
    console.log("theObject.vertexBuffer texcoordBuffer indexBuffer error");
    return null;
  }
    
    theObject.numIndices = indices.length;
    console.log(theObject.numIndices);
    
    //解绑
    gl.bindBuffer(gl.ARRAY_BUFFER, null );
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    
    return theObject;

}

//创建顶点缓冲区和索引缓冲区
function initVertexBuffersForPlane(gl) {
  // Create face
  //  v1------v0
  //  |        |
  //  |        |
  //  |        |
  //  v2------v3

  // Vertex coordinates
  var vertices = new Float32Array([
    1.0, 1.0, 0.0,  -1.0, 1.0, 0.0,  -1.0,-1.0, 0.0,   1.0,-1.0, 0.0    // v0-v1-v2-v3
  ]);

  // Texture coordinates
  var texCoords = new Float32Array([1.0, 1.0,   0.0, 1.0,   0.0, 0.0,   1.0, 0.0]);

  // Indices of the vertices
  var indices = new Uint8Array([0, 1, 2,   0, 2, 3]);
  var theObject = new Object();
  theObject.vertexBuffer = initArrayBufferForLateruse(gl, vertices, 3, gl.FLOAT);
  theObject.texcoordBuffer = initArrayBufferForLateruse(gl, texCoords, 2, gl.FLOAT);
  theObject.indexBuffer = initElementArrayBufferForLaterUse(gl, indices, gl.UNSIGNED_BYTE);
  if( !theObject.vertexBuffer || !theObject.texcoordBuffer || !theObject.indexBuffer)
  {
    return null;
  }
    
    theObject.numIndices = indices.length;
    
    //解绑
    gl.bindBuffer(gl.ARRAY_BUFFER, null );
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    
    return theObject;

}


function initElementArrayBufferForLaterUse(gl, data, type)
{
    // Create a buffer object
    var indexBuffer = gl.createBuffer();
    if (!indexBuffer)
    {
        console.log('Failed to create the buffer object');
        return -1;
    }

    // Write the indices to the buffer object
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW);
    
    indexBuffer.type = type;

    return indexBuffer;
}
function initArrayBufferForLateruse(gl, data, num, type) {
  var buffer = gl.createBuffer();   // Create a buffer object
  if (!buffer) {
    console.log('Failed to create the buffer object');
    return false;
  }
  // Write date into the buffer object
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
 
  buffer.num = num;
  buffer.type = type
  return buffer;
}
function loadTexture(gl, texture, u_Sampler, image)
{
    //对纹理图像进行y轴翻转
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
    //开启0号纹理单元
    //gl.activeTexture(gl.TEXTURE0);
    //向target绑定纹理对象
    gl.bindTexture(gl.TEXTURE_2D, texture);
    //配置纹理参数
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    //配置纹理图像
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    //将0号纹理传递给着色器
    gl.uniform1i(u_Sampler, 0 );
    //解绑纹理
    gl.bindTexture(gl.TEXTURE_2D, null);

}

function initTextures(gl,program)
{    
     //创建纹理对象
    var texture = gl.createTexture();
    if (!texture)
    {
        console.log('Failed to create the texture object');
        return false;
    }
  console.log('success to create the texture object');
    //获取u_Sampler的存储位置
    var u_Sampler = gl.getUniformLocation(program,'u_Sampler');
    if (!u_Sampler)
    {
        console.log('Failed to get the storage location of u_Sampler');
        return false;
    }
    console.log('success to get the storage location of u_Sampler');
    //创建一个image对象
    var image = new Image();
    if (!image)
    {
        console.log('Failed to create the image object');
        return false;
    }
    console.log('success to create the image object');
    //注册图像加载事件的响应函数
    image.onload = function()
    {
        loadTexture(gl, texture, u_Sampler, image);
    }
    image.src = 'http://localhost:8080/apps/resources/sky.jpg';    
    return texture;
}

function initFrameBufferObject(gl)
{
    var frameBuffer, texture, depthBuffer;
    var error = function()
    {
        if(frameBuffer)
        {
            gl.deleteFrameBuffer(frameBuffer);
        }
        if(texture)
        {
            gl.deleteTexture(texture);
        }
        if(depthBuffer)
        {
            gl.deleteRenderBuffer(depthBuffer);
        }
        return null;
    }
    //创建FBO
    frameBuffer = gl.createFramebuffer();
    if(!frameBuffer)
    {
        console.log('Failed to create frame buffer object');
        return error();
    }
    
    //创建纹理对象,并设置大小和参数
    texture = gl.createTexture();
    if(!texture)
    {
        console.log('Failed to create texture object');
        return error();
    }
    //绑定对象到目标
    gl.bindTexture(gl.TEXTURE_2D, texture);
    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 );
    frameBuffer.texture = texture;
    
    //创建渲染缓冲区对象,并设置大小和参数
    depthBuffer = gl.createRenderbuffer();
    if(!depthBuffer)
    {
        console.log('Failed to create renderbuffer object');
        return error();
    }
    //连接对象到目标
    gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT );
    
    //连接纹理对象和渲染缓冲区对象到FBO
    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);
    
    //判断FBO是否配置正确
    var e = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
    if(gl.FRAMEBUFFER_COMPLETE !== e )
    {
        console.log('Frame buffer object is incomplete:' + e.toString());
        return error();
    }
    
    //解绑缓存对象
    gl.bindFramebuffer(gl.FRAMEBUFFER, null );
    gl.bindTexture(gl.TEXTURE_2D, null );
    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    
    return frameBuffer;    
    
}
 
   
function  initAttributeVariable(gl, a_attribute, buffer, bufferNum, bufferType )
{
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer );
    gl.vertexAttribPointer(a_attribute, bufferNum, bufferType, false, 0, 0 );
    gl.enableVertexAttribArray(a_attribute);
}

function drawTexturedObject(gl, program, positionHandle, texCoordHandle,MvpMatrixHandle,theObject, texture )
{
    initAttributeVariable(gl, positionHandle, theObject.vertexBuffer, theObject.vertexBuffer.num, theObject.vertexBuffer.type );
    initAttributeVariable(gl, texCoordHandle, theObject.texcoordBuffer, theObject.texcoordBuffer.num, theObject.texcoordBuffer.type );
    
    //绑定纹理对象到目标
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture );
    
    //绘制
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, theObject.indexBuffer );
    gl.drawElements(gl.TRIANGLES, theObject.numIndices, theObject.indexBuffer.type, 0 );
}

function drawTexturedCube(gl, program,positionHandle, texCoordHandle,MvpMatrixHandle, theObject, angle, texture, g_modelMatrix, viewProjMatrix,  g_mvpMatrix)
{
    g_modelMatrix.setRotate(20.0, 1.0, 0.0, 0.0 );
    g_modelMatrix.rotate(angle, 0.0, 1.0, 0.0 );
    
    g_mvpMatrix.set(viewProjMatrix);
    g_mvpMatrix.multiply(g_modelMatrix);
    gl.uniformMatrix4fv(MvpMatrixHandle, false, g_mvpMatrix.elements );
    drawTexturedObject(gl, program, positionHandle, texCoordHandle,MvpMatrixHandle,theObject, texture );
    console.log(theObject.numIndices);
}

function drawTexturedPlane(gl, program,positionHandle, texCoordHandle,MvpMatrixHandle, theObject, angle, texture, g_modelMatrix, viewProjMatrix,  g_mvpMatrix)
{    
    g_modelMatrix.setTranslate(0,0,1);
    g_modelMatrix.rotate(20.0, 1.0, 0.0, 0.0 );
    g_modelMatrix.rotate(angle, 0.0, 1.0, 0.0 );
    
    g_mvpMatrix.set(viewProjMatrix);
    g_mvpMatrix.multiply(g_modelMatrix);
    gl.uniformMatrix4fv(MvpMatrixHandle, false, g_mvpMatrix.elements );
    drawTexturedObject(gl, program,positionHandle, texCoordHandle, MvpMatrixHandle,theObject, texture );
}

    var canvas = document.getElementById("test");
    //创建webgl渲染上下文
    var gl = canvas.getContext("webgl");
    if(!gl)
    {
        console.log("wrong");
    }
    else
    {
        console.log("right");
    }
    //初始化着色器

    var vertexShader = createShader(gl,gl.VERTEX_SHADER,vertexShaderSource);
    var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER, fragmentShaderSource);
    var program = createProgram(gl, vertexShader, fragmentShader);
    var positionHandle = gl.getAttribLocation(program, 'a_Position');
    var texCoordHandle = gl.getAttribLocation(program, 'a_TexCoord');
    var MvpMatrixHandle = gl.getUniformLocation(program, 'u_MvpMatrix');

    gl.useProgram(program);
    //创建顶点数组
    var cube = initVertexBuffersForCube(gl);
    
    var plane = initVertexBuffersForPlane(gl);
    
    if(!cube || !plane )
    {
        console.log('Failed to set the Vertex information');
    }
    
    
    
    //设置纹理
    var texture = initTextures(gl,program);
    if( !texture )
    {
        console.log('Failed to initialize the texture');
    }
    
    //创建帧缓存对象
    var fbo = initFrameBufferObject(gl);
    if(!fbo)
    {
        console.log('Failed to initialize FBO');
    }
 
    //模型矩阵
    var g_modelMatrix = new Matrix4();
    //模型视图投影矩阵
    var g_mvpMatrix = new Matrix4();
    var rotateDeg = 1.0;
    //开启隐藏面消除功能
    gl.enable(gl.DEPTH_TEST);
    
    var viewProjMatrix = new Matrix4();
    viewProjMatrix.setPerspective(30, canvas.width / canvas.height,0.1, 100.0);
    viewProjMatrix.lookAt(0,0,7,0,0,0,0,1,0);  
    
    var viewProjMatrixFBO = new Matrix4();
    viewProjMatrixFBO.setPerspective(30, OFFSCREEN_WIDTH / OFFSCREEN_HEIGHT,0.1, 100.0);
    viewProjMatrixFBO.lookAt(0,2.0,7,0,0,0,0,1,0);  
    
    var mytick = function()
    {
    
    //绑定帧缓冲区对象
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo );
    //定义离线绘图的绘图区域
    gl.viewport(0, 0, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT );
    //清空帧缓冲区
    gl.clearColor( 0.2, 0.2, 0.4, 1.0 );
    //gl.clearColor( 1.0, 0.0, 0.0, 1.0 );
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
    //绘制立方体
    drawTexturedCube(gl, program, positionHandle, texCoordHandle, MvpMatrixHandle,cube, rotateDeg, texture, g_modelMatrix, viewProjMatrixFBO, g_mvpMatrix);
    //
    //解绑fbo
    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 );
    drawTexturedPlane(gl, program, positionHandle, texCoordHandle,MvpMatrixHandle,plane, 0, fbo.texture, g_modelMatrix, viewProjMatrix, g_mvpMatrix);
    
    rotateDeg += 1
    requestAnimationFrame(mytick);
    }
    mytick();
    
    </script>
</body>
</html>

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值