shadowmap

这个例子其实没什么,主要是要注意光线坐标系的传递,以及纹理的传递

1,光源坐标系的传递,主要是要比较深度图的大小

        gl.useProgram(program_shadowMap);
     ....
        mvpMatrixFromLight_triangle.set(g_mvpMatrix);       

....
        mvpMatrixFromLight_plane.set(g_mvpMatrix);        
    
.........
        gl.useProgram(program_Normal);   


        gl.uniformMatrix4fv(MvpMatrixFromLightHandle_Normal, false, mvpMatrixFromLight_triangle.elements );

.......
        gl.uniformMatrix4fv(MvpMatrixFromLightHandle_Normal, false, mvpMatrixFromLight_plane.elements );

 

2,纹理的绑定,这里绑定是按照第几个纹理绑定的,

gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, fbo.texture);
 

绑定后,正常绘制后传递时,

var shadowMapHandle_Normal = gl.getUniformLocation(program_Normal, 'u_ShadowMap'); gl.uniform1i(shadowMapHandle_Normal, 0 );

 

具体代码如下:

<html>
<head>11</head>
<body>
<canvas id = "test" width = "800" height = "800">canvas </canvas>
<script src = "webgltest/cuon-matrix.js"></script>
<script >

//生成阴影贴图的顶点缓冲区
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 =
    'precision mediump float;\n' +
    'void main() {\n' +
    'gl_FragColor = vec4(gl_FragCoord.z, 0.0, 0.0, 0.0); \n' +
    '}\n';
//正常绘制时的顶点着色器
var vertexShaderSource =
    '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';

//片元着色器
var fragmentShaderSource =
    'precision mediump float;\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' +
    'float depth = rgbaDepth.r;\n' +
    'float visibility = (shadowCoord.z > depth + 0.005 ) ? 0.7 : 1.0;\n' +
    'gl_FragColor = vec4(v_Color.rgb * visibility, v_Color.a ); \n' +
    '}\n';
    
//离屏绘制尺寸
var OFFSCREEN_WIDTH = 1024;
var OFFSCREEN_HEIGHT = 1024;
var LIGHT_X     = 0.0;
var LIGHT_Y = 7.0;
var LIGHT_Z = 2.0;
var g_modelMatrix = new Matrix4();
var g_mvpMatrix = new Matrix4();

//创建着色器方法,输入参数:渲染上下文,着色器类型,数据源
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;
    }
    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)
    {
        return program;
    }
    gl.deleteProgram(program);
}

//创建顶点缓冲区和索引缓冲区
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 theObject = new Object();
  theObject.vertexBuffer = initArrayBufferForLateruse(gl, vertices, 3, gl.FLOAT);
  theObject.colorBuffer = initArrayBufferForLateruse(gl, colors, 3, gl.FLOAT);
  theObject.indexBuffer = initElementArrayBufferForLaterUse(gl, indices, gl.UNSIGNED_BYTE);
  if( !theObject.vertexBuffer || !theObject.colorBuffer || !theObject.indexBuffer)
  {
    return null;
  }
    
    theObject.numIndices = indices.length;
    
    //解绑
    gl.bindBuffer(gl.ARRAY_BUFFER, null );
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    
    return theObject;

}

//创建顶点缓冲区和索引缓冲区
function initVertexBuffersForPlane(gl)
{
   // 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 theObject = new Object();
  theObject.vertexBuffer = initArrayBufferForLateruse(gl, vertices, 3, gl.FLOAT);
  theObject.colorBuffer = initArrayBufferForLateruse(gl, colors, 3, gl.FLOAT);
  theObject.indexBuffer = initElementArrayBufferForLaterUse(gl, indices, gl.UNSIGNED_BYTE);
  if( !theObject.vertexBuffer || !theObject.colorBuffer || !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)
    {
        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)
  {
    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 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)
    {
        return error();
    }
    
    //创建纹理对象,并设置大小和参数
    texture = gl.createTexture();
    if(!texture)
    {
        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)
    {
        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 )
    {
        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 drawTriangle(gl,positionHandle, colorHandle,MvpMatrixHandle, theObject, angle,  viewProjMatrix)
{
    g_modelMatrix.setRotate(angle, 0, 1, 0 );

    initAttributeVariable(gl, positionHandle, theObject.vertexBuffer, theObject.vertexBuffer.num, theObject.vertexBuffer.type );
    initAttributeVariable(gl, colorHandle, theObject.colorBuffer, theObject.colorBuffer.num, theObject.colorBuffer.type );
    g_mvpMatrix.set(viewProjMatrix);
    g_mvpMatrix.multiply(g_modelMatrix);
    gl.uniformMatrix4fv(MvpMatrixHandle, false, g_mvpMatrix.elements );
    //绘制
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, theObject.indexBuffer );
    gl.drawElements(gl.TRIANGLES, theObject.numIndices, theObject.indexBuffer.type, 0 );    
    
}
function drawTriangleFBO(gl,positionHandle,MvpMatrixHandle, theObject, angle, viewProjMatrix)
{
    g_modelMatrix.setRotate(angle, 0, 1, 0 );
    initAttributeVariable(gl, positionHandle, theObject.vertexBuffer, theObject.vertexBuffer.num, theObject.vertexBuffer.type );
    g_mvpMatrix.set(viewProjMatrix);
    g_mvpMatrix.multiply(g_modelMatrix);
    gl.uniformMatrix4fv(MvpMatrixHandle, false, g_mvpMatrix.elements );
    //绘制
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, theObject.indexBuffer );
    gl.drawElements(gl.TRIANGLES, theObject.numIndices, theObject.indexBuffer.type, 0 );    
    
    
}
function drawPlane(gl,positionHandle, colorHandle,MvpMatrixHandle, theObject, viewProjMatrix)
{        
    g_modelMatrix.setRotate(-45.0, 0, 1, 1 );
    
    initAttributeVariable(gl, positionHandle, theObject.vertexBuffer, theObject.vertexBuffer.num, theObject.vertexBuffer.type );
    initAttributeVariable(gl, colorHandle, theObject.colorBuffer, theObject.colorBuffer.num, theObject.colorBuffer.type );
    g_mvpMatrix.set(viewProjMatrix);
    g_mvpMatrix.multiply(g_modelMatrix);
    gl.uniformMatrix4fv(MvpMatrixHandle, false, g_mvpMatrix.elements );

    //绘制
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, theObject.indexBuffer );
    gl.drawElements(gl.TRIANGLES, theObject.numIndices, theObject.indexBuffer.type, 0 );    
}    

function drawPlaneFBO(gl, positionHandle,MvpMatrixHandle, theObject, viewProjMatrix)
{        
    g_modelMatrix.setRotate(-45.0, 0, 1, 1 );
    
    initAttributeVariable(gl, positionHandle, theObject.vertexBuffer, theObject.vertexBuffer.num, theObject.vertexBuffer.type );
    g_mvpMatrix.set(viewProjMatrix);
    g_mvpMatrix.multiply(g_modelMatrix);
    gl.uniformMatrix4fv(MvpMatrixHandle, false, g_mvpMatrix.elements );
    //绘制
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, theObject.indexBuffer );
    gl.drawElements(gl.TRIANGLES, theObject.numIndices, theObject.indexBuffer.type, 0 );    
    
}

    var canvas = document.getElementById("test");
    //创建webgl渲染上下文
    var gl = canvas.getContext("webgl");
    //初始化生成阴影贴图的着色器
    
    var vertexShader_shadowMap = createShader(gl,gl.VERTEX_SHADER,SHADOW_VSHADER_SOURCE);
    var fragmentShader_shadowMap = createShader(gl,gl.FRAGMENT_SHADER, SHADOW_FSHADER_SOURCE);
    var program_shadowMap = createProgram(gl, vertexShader_shadowMap, fragmentShader_shadowMap);
    var positionHandle_shadowMap = gl.getAttribLocation(program_shadowMap, 'a_Position');
    var MvpMatrixHandle_shadowMap = gl.getUniformLocation(program_shadowMap, 'u_MvpMatrix');
    if(positionHandle_shadowMap < 0 || !MvpMatrixHandle_shadowMap )
    {
        console.log('Failed to get program_shadowMap variable');
    }

    var vertexShader_Normal = createShader(gl,gl.VERTEX_SHADER,vertexShaderSource);
    var fragmentShader_Normal = createShader(gl,gl.FRAGMENT_SHADER, fragmentShaderSource);
    var program_Normal = createProgram(gl, vertexShader_Normal, fragmentShader_Normal);
    var positionHandle_Normal = gl.getAttribLocation(program_Normal, 'a_Position');
    var colorHandle_Normal = gl.getAttribLocation(program_Normal, 'a_Color');
    var MvpMatrixHandle_Normal = gl.getUniformLocation(program_Normal, 'u_MvpMatrix');
    var MvpMatrixFromLightHandle_Normal = gl.getUniformLocation(program_Normal, 'u_MvpMatrixFromLight');
    var shadowMapHandle_Normal = gl.getUniformLocation(program_Normal, 'u_ShadowMap');
    if( positionHandle_Normal < 0 || colorHandle_Normal < 0 || !MvpMatrixHandle_Normal || !MvpMatrixFromLightHandle_Normal || !shadowMapHandle_Normal )
    {
        console.log('Failed to get program_Normal variable');
    }

    //创建顶点数组
    var triangle = initVertexBuffersForTriangle(gl);    
    var plane = initVertexBuffersForPlane(gl);
    
    if(!triangle || !plane )
    {
        console.log('Failed to set the Vertex information');
    }
            
    //创建帧缓存对象
    var fbo = initFrameBufferObject(gl);
    if(!fbo)
    {
        console.log('Failed to initialize FBO');
    }
    
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, fbo.texture);
 
    //模型矩阵
    //var g_modelMatrix = new Matrix4();
    //模型视图投影矩阵
    //var g_mvpMatrix = new Matrix4();
    var rotateDeg = 1.0;
    
    gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
    //开启隐藏面消除功能
    gl.enable(gl.DEPTH_TEST);
    
    var viewProjMatrixFromLight = new Matrix4();
    viewProjMatrixFromLight.setPerspective(70.0, OFFSCREEN_WIDTH / OFFSCREEN_HEIGHT,1.0, 100.0);
    viewProjMatrixFromLight.lookAt(LIGHT_X,LIGHT_Y,LIGHT_Z,0,0,0,0,1,0);  
    
    var viewProjMatrix = new Matrix4();
    viewProjMatrix.setPerspective(45, canvas.width / canvas.height,1.0, 100.0);
    viewProjMatrix.lookAt(10,20,30,9.0,0,0,0,1,0);  
    
    var mvpMatrixFromLight_triangle = new Matrix4();
    var mvpMatrixFromLight_plane = new Matrix4();
    var mytick = function()
    {
        
        //绑定帧缓冲区对象
        gl.bindFramebuffer(gl.FRAMEBUFFER, fbo );
        //定义离线绘图的绘图区域
        gl.viewport(0, 0, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT );    
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
        gl.useProgram(program_shadowMap);
        
        //绘制三角形
        drawTriangleFBO(gl, positionHandle_shadowMap, MvpMatrixHandle_shadowMap,triangle, rotateDeg,viewProjMatrixFromLight);      
        mvpMatrixFromLight_triangle.set(g_mvpMatrix);        
        drawPlaneFBO(gl, positionHandle_shadowMap, MvpMatrixHandle_shadowMap,plane, viewProjMatrixFromLight);
        mvpMatrixFromLight_plane.set(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 );
        gl.useProgram(program_Normal);    
        gl.uniform1i(shadowMapHandle_Normal, 0 );
        gl.uniformMatrix4fv(MvpMatrixFromLightHandle_Normal, false, mvpMatrixFromLight_triangle.elements );
        drawTriangle(gl, positionHandle_Normal, colorHandle_Normal, MvpMatrixHandle_Normal,triangle, rotateDeg, viewProjMatrix);    
        gl.uniformMatrix4fv(MvpMatrixFromLightHandle_Normal, false, mvpMatrixFromLight_plane.elements );
        drawPlane(gl, positionHandle_Normal, colorHandle_Normal, MvpMatrixHandle_Normal, plane, viewProjMatrix);
    
        rotateDeg += 1
        requestAnimationFrame(mytick);
    }
    mytick();
    
    </script>
</body>
</html>

图示如下:

提到了马赫带,果然去掉那个微调值出现了条纹

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值