Webgl-超级基础随笔5-贴图阴影绘制

纹理贴图旋转-阴影绘制

以texture_rotateCude.html为基础

1.新建着色器

1.//创建一个阴影顶点、片元着色器

var SHADOW_VSHADER_SOURCE =

'attribute vec4 a_Position;\n' +

'uniform mat4 u_MvpMatrix;\n' +

'uniform mat4 u_rotateMatrix;\n' +

'void main() {\n' +

//gl_Position有深度记录Fshader中可以拿到

' gl_Position = (a_Position.y >= -1.0) ? (u_MvpMatrix * u_rotateMatrix * a_Position) : (u_MvpMatrix * a_Position);\n' +

'}\n';

// Fragment shader program for generating a shadow map

var SHADOW_FSHADER_SOURCE =

'#ifdef GL_ES\n' +

'precision mediump float;\n' +

'#endif\n' +

'void main() {\n' +

//gl_FragCoord定位片元位置,记录纹理信息

' gl_FragColor = vec4(gl_FragCoord.z, 0.0, 0.0, 0.0);\n' + // Write the z-value in R

'}\n';

  1. 在主顶点着色器中

'uniform mat4 u_MvpMatrixFromLight;\n' +//从光源出发的视图投影矩阵

'varying vec4 v_PositionFromLight;\n' +//光源出发的模型位置

Main

' v_PositionFromLight = u_MvpMatrixFromLight * a_Position;\n' +//确定在光源下的模型位置

  1. 在主Fragment shader中

'uniform sampler2D u_ShadowMap;\n' +//传阴影贴图

'varying vec4 v_PositionFromLight;\n' +

Main

//阴影

' vec3 shadowCoord = (v_PositionFromLight.xyz/v_PositionFromLight.w)/2.0 + 0.5;\n' +//坐标转换(webGL的XY坐标-1-1->纹理坐标0-1)

' vec4 rgbaDepth = texture2D(u_ShadowMap, shadowCoord.xy);\n' +//取纹理值

' float depth = rgbaDepth.r;\n' + // 取以光源相机为视角的深度

' float visibility = (shadowCoord.z > depth + 0.005) ? 0.5 : 1.0;\n' +//比较渲染片元与shadowmap的情况,描述阴影

//颜色渲染(阴影渲染)

' gl_FragColor = vec4(r_Color.rgb * visibility, r_Color.a);\n' +

  1. 将关于program的封装为

//创建程序

function createProgram (gl, vSource, fSource) {

var program = gl.createProgram()

// define vertex shader

var vertexShader = createShader(gl, vSource, gl.VERTEX_SHADER)

// define frament shader

var fragmentShader = createShader(gl, fSource, gl.FRAGMENT_SHADER)

 

// attach shader to program

gl.attachShader(program, vertexShader)

gl.attachShader(program, fragmentShader)

// link program to context

gl.linkProgram(program)

return program

}

在主函数JS中

var normalProgram = createProgram(gl, VSHADER_SOURCE, FSHADER_SOURCE)//主程序

var shadowProgram = createProgram(gl, SHADOW_VSHADER_SOURCE, SHADOW_FSHADER_SOURCE)//shadowmap程序

gl.useProgram(normalProgram)

gl.program = normalProgram

  1. 重新定义initVertexBuffers

数据不变

其他改为

// Create a buffer object

var o = new Object();

var indexBuffer = gl.createBuffer();

// Write the indices to the buffer object主缓冲区灌入数据

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);

gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

o.indexBuffer = indexBuffer;

o.positionBuffer = initArrayBuffer(gl, vertices, 3, gl.FLOAT, gl.program);

o.normalBuffer = initArrayBuffer(gl, normals, 3, gl.FLOAT, gl.program)

o.texCoordBuffer = initArrayBuffer(gl, verticesTexCoords, 2, gl.FLOAT, gl.program)

//阴影缓冲区灌入数据

var shadowIndexBuffer = gl.createBuffer();

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, shadowIndexBuffer);

gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

o.shadowIndexBuffer = shadowIndexBuffer;

o.shadowPositionBuffer = initArrayBuffer(gl, vertices, 3, gl.FLOAT, shadowProgram);

o.n = indices.length;

return o;//返回对象

  1. 封装initAttributeVariable

//绑定attribute

function initAttributeVariable(gl,a_attribute,buffer) {

// Assign the buffer object to the attribute variable

// var a_attribute = gl.getAttribLocation(gl.program, attribute);

// if (a_attribute < 0) {

// console.log('Failed to get the storage location of ' + attribute);

// return false;

// }

gl.bindBuffer(gl.ARRAY_BUFFER, buffer);//绑定缓冲区

//将当前绑定到gl.ARRAY_BUFFER的缓冲区到顶点缓存区

gl.vertexAttribPointer(a_attribute, buffer.num, buffer.type, false, 0, 0);

// Enable the assignment of the buffer object to the attribute variable

gl.enableVertexAttribArray(a_attribute);//许可缓冲区分配变量

}

  1. 改变initArrayBuffer

function initArrayBuffer(gl, data, num, type, program) {

// Create a buffer object

var buffer = gl.createBuffer();

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);

 

gl.bindBuffer(gl.ARRAY_BUFFER, null);//清空bindBuffer中的gl.ARRAY_BUFFER缓存区

buffer.num = num

buffer.type = type

return buffer;

}

  1. 在JS主程中

// write the positions of vertices to a vertex shader

var o = initVertexBuffers(gl)

var n = o.n

initTexture(gl, n)//加载纹理贴图

 

var fbo = initFramebufferObject(gl);//创建阴影对象

gl.activeTexture(gl.TEXTURE0); // Set a texture object to the texture unit激活

gl.bindTexture(gl.TEXTURE_2D, fbo.texture);//绑定纹理

 

 

//阴影设置

var u_MvpMatrixFromLight = gl.getUniformLocation(gl.program, 'u_MvpMatrixFromLight');

var u_ShadowMvpMatrix = gl.getUniformLocation(shadowProgram, 'u_MvpMatrix');

var u_ShadowRotateMatrix = gl.getUniformLocation(shadowProgram, 'u_rotateMatrix');

var shadowMvpMatrix = new Matrix4();

shadowMvpMatrix.setPerspective(30, 1, 1, 100);

shadowMvpMatrix.lookAt(0, 21, 0, 0, 0, 0, 0, 0, 1);//阴影位置

gl.uniformMatrix4fv(u_MvpMatrixFromLight, false, shadowMvpMatrix.elements)

//attribute获取设置

var u_ShadowMap = gl.getUniformLocation(gl.program, 'u_ShadowMap');//阴影纹理

var positionLocation = gl.getAttribLocation(gl.program, 'a_Position');

var normalLocation = gl.getAttribLocation(gl.program, 'a_Normal');

var texCoordLocation = gl.getAttribLocation(gl.program, 'a_TexCoord');

var shadowPositionLocation = gl.getAttribLocation(shadowProgram, 'a_Position');

  1. draw中

//绘制阴影的片元

gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);

gl.viewport(0, 0, OFFSCREEN_HEIGHT, OFFSCREEN_HEIGHT);

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Clear FBO

gl.useProgram(shadowProgram); // Set shaders for generating a shadow map

initAttributeVariable(gl, shadowPositionLocation, o.shadowPositionBuffer);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, o.shadowIndexBuffer);

gl.uniformMatrix4fv(u_ShadowRotateMatrix, false, rotateMatrix.elements);

gl.uniformMatrix4fv(u_ShadowMvpMatrix, false, shadowMvpMatrix.elements);

gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);

 

//回到主程序改变贴图添加阴影

gl.bindFramebuffer(gl.FRAMEBUFFER, null); // Change the drawing destination to color buffer

gl.viewport(0, 0, canvas.width, canvas.height);

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Clear color and depth buffer

gl.useProgram(gl.program);

initAttributeVariable(gl, normalLocation, o.normalBuffer);

initAttributeVariable(gl, positionLocation, o.positionBuffer);

initAttributeVariable(gl, texCoordLocation, o.texCoordBuffer);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, o.indexBuffer);

gl.uniform1i(u_ShadowMap, 0); // Pass 0 because gl.TEXTURE0 is enabledする

gl.uniformMatrix4fv(u_RotateMatrix, false, rotateMatrix.elements);

// Draw the cube索引方式绘制(三角面,绘制点数,前面的数据类型,偏移)

gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);

  1. initFramebufferObject

//初始化片元对象-阴影帧缓存区创建

function initFramebufferObject(gl) {

var framebuffer, texture, depthBuffer;

 

// Define the error handling function

var error = function() {

if (framebuffer) gl.deleteFramebuffer(framebuffer);

if (texture) gl.deleteTexture(texture);

if (depthBuffer) gl.deleteRenderbuffer(depthBuffer);

return null;

}

// Create a framebuffer object (FBO)

framebuffer = gl.createFramebuffer();//创建片元缓冲区

if (!framebuffer) {

console.log('Failed to create frame buffer object');

return error();

}

// Create a texture object and set its size and parameters

texture = gl.createTexture(); // Create a texture object

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);//将纹理放入activeTexture

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);//纹理映射

// Create a renderbuffer object and Set its size and parameters

//真正使用的缓冲区

depthBuffer = gl.createRenderbuffer(); // Create a renderbuffer object

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);//分配存储区

// Attach the texture and the renderbuffer object to the 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);

// Check if FBO is configured correctly

var e = gl.checkFramebufferStatus(gl.FRAMEBUFFER);//检查帧缓冲区状态

if (gl.FRAMEBUFFER_COMPLETE !== e) {

console.log('Frame buffer object is incomplete: ' + e.toString());

return error();

}

framebuffer.texture = texture; // keep the required object

// Unbind the buffer object清空绑定

gl.bindFramebuffer(gl.FRAMEBUFFER, null);

gl.bindTexture(gl.TEXTURE_2D, null);

gl.bindRenderbuffer(gl.RENDERBUFFER, null);

return framebuffer;

}

结束。源码github。 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值