[前端拓展]结合渲染管线学习WebGL-01

444 阅读2分钟

目标

结合WebGL渲染管线学习WebGL的基本API

结合渲染管线学习WebGL API

WebGL渲染管线

OpenGL ES2.0渲染管线.png

利用WebGL API 控制渲染管线

  • 创建Shader程序
  • 直接向Shader传入数据
  • 向各缓冲区写入数据,并利用缓冲区向Shader传入数据
  • 配置渲染的一些操作,比如设定混合模式 ,开关一些片元操作

创建Shader程序

创建Shader——>导入glsl代码——>编译Shader——>创建Program——>连接Shader对象——>链接Program——>使用Program

//创建Shader对象
vertex_shader = webglContext.createShader(webglContext.VERTEX_SHADER)  //顶点着色器
fragment__shader = webglContext.createShader(webglContext.FRAGMENT_SHADER)  //片元着色器

//导入glsl代码
webglContext.shaderSource(vertex_shader, vertex_glsl)
webglContext.shaderSource(fragment_shader, fragment_glsl)

//编译Shader
webglContext.compileShader(vertex_shader)
webglContext.compileShader(fragment_shader)

//获取编译状态
Boolean webglContext.getShaderParameter(vertex_shader, webglContext.COMPILE_STATUS)
Boolean webglContext.getShaderParameter(fragment_shader, webglContext.COMPILE_STATUS)

//创建Program对象
program = webglContext.createProgram()

//连接编译好的Shader代码
webglContext.attachShader(program, vertex_shader)
webglContext.attachShader(program, fragment_shader)

//链接Program程序
webglContext.linkProgram(program)

//获取链接状态
Boolean webglContext.getProgramParameter(program, webglContext.LINK_STATUS)

//使用程序
webglContext.useProgram(program)

获取Shader中的变量并传值

创建指针变量——>获取或绑定Shader变量地址——>利用webglContext的Setter方法进行传值

//针对Attribute
var attriName
webglContext.bindAttribLocation(program, attriName, '在shader中的变量名') //绑定js变量和Shader变量
webglContext.enableVertexAttribArray(attriName)   //激活该js变量
webglContext.vertexAttribPointer(attriName, ....)  //传值,此时是读取顶点缓冲区的值进行传送

or

var attriName
attriName = webglContext.getAttribLocation(program, '在Shader中的变量名')  //获取变量
webglContext.vertexAttrib...(attriName, ....)   //赋值

//针对Uniform
var uniformName
uniformName = webglContext.getUniformLocation(program, '在shader中的uniform名')  //获取unifrom变量
webglContext.uniform...(uniformName, ...)  //赋值Uniform变量

使用顶点缓冲区

创建缓冲区——>绑定缓冲区——>导入数据进入缓冲区

//创建缓冲区
buffer = webglContext.createBuffer()

//绑定Buffer
webglContext.bindBuffer(webglContext.ARRAY_BUFFER, buffer)

//向Buffer里传值
webglContext.bufferData(webglContext.ARRAT_BUFFER, data, ...) 

使用索引缓冲区

在使用顶点缓冲区的前提下,进行索引缓冲区的使用。 创建缓冲区——>绑定缓冲区——>导入数据进入缓冲区

buffer = webglContext.createBuffer()
webglContext.bindBuffer(webglContext.ELEMENT_ARRAY_BUFFER, buffer)
webglContext.bufferData(webglContext.ELEMENT_ARRAT_BUFFER, data, ...) 

使用纹理缓冲区

//创建纹理,加载图像
texture = webgl.createTexture()
texture.image = new Image()
texture.image.src = Image_url
texture.image.onload = () => {
    // 绑定纹理缓冲区,并进行相关配置
    webglContext.bindTexture(webglContext.TEXTURE_2D, texture)
    webglContext.texImage2D(webglContext.TEXTURE_2D, 0, webglContext.RGBA, webglContext.RGBA, webglContext.UNSIGNED_BYTE, texture.image)
    webglContext.texParameteri(webglContext.TEXTURE_2D, webglContext.TEXTURE_MAG_FILTER, webgl.NEAREST)
    webglContext.texParameteri(webglContext.TEXTURE_2D, webglContext.TEXTURE_MIN_FILTER, webgl.NEAREST)
    webglContext.texParameteri(webglContext.TEXTURE_2D, webglContext.TEXTURE_WRAP_S, webglContext.CLAMP_TO_EDGE)
    webglContext.texParameteri(webglContext.TEXTURE_2D, webglContext.TEXTURE_WRAP_T, webglContext.CLAMP_TO_EDGE)
    webglContext.bindTexture(webglContext.TEXTURE_2D, null)  //恢复纹理缓冲区默认状态
    
    //激活纹理缓冲区
    webglContext.activeTexture(webglContext.TEXTURE0)   //激活纹理缓冲区
    webglContext.bindTexture(webglContext.TEXTURE_2D, texture)  // 切换纹理
    webglContext.uniformli(shader中的纹理变量, 0)  //0为纹理所在的缓冲区索引
}

帧缓冲区

frambuffer = webglContext.createFrameBuffer()
webglContext.bindFramebuffer(webglContext.FRAMEBUFFER, framebuffer)  //创建帧缓冲区
depthbuffer = webglContext.createRenderbuffer()         //创建渲染缓冲区作为帧缓冲区的深度缓冲区
webglContext.bindRenderbuffer(webglContext.RENDERBUFFER, depthbuffer)
webglContext.renderbufferStorage(webglContext.RENDERBUFFER, webglContext.DEPTH_COMPONET16, width, height)
webglContext.framebufferRenderbuffer(webglContext.FRAMEBUFFER, webglContext.DEPTH_ATTACHMENT, webglContext.RENDERBUFFER, depthbuffer)

texture = webglContext.createTexture()
webglContext.framebufferTexture2D(webglContext.FRAMEBUFFER, webglContext.COLOR_ATTACHMENT0, webglContext.TEXTURE_2D, texture, 0)    //创建纹理作为帧缓冲区的颜色缓冲区

顶点状态缓冲区

保存VertexShader的状态

VAOExt = webglContext.getExtension('OES_vertex_array_object')
vao = VAOExt.createVertexArrayOES()
VAOExt.bindVertexArrayOES(vao)
...状态改变
VAOExt.bindVertexArrayOES(null)

设置图元类型并绘制

启动绘制以及设置图元装配的类型

webglContext.drawArrays(Type, ...) //以顶点缓冲区数据进行绘制
webglContext.drawElements(Type, ...)  //以索引缓冲区数据进行绘制

混合渲染模式

webglContext.enable(webglContext.DEPTH_TEST)
webglContext.depthFunc(webglContext.LEQUEAL)
webglContext.blendFunc(webglContext.SRC_ALPHA, webglContext.ONE) //等其他混合渲染模式
webglContext.enable(webglContext.BLEND)   //开启混合渲染