WebGL attribute与uniform与API

1,111 阅读5分钟

绑定顶点数据的API

// 创建缓冲区对象
WebGLBuffer? createBuffer();

// 允许使用buffer表示的缓冲区对象并将其绑定到target表示的目标上
// 下文中的target参数值
const GLenum ARRAY_BUFFER                   = 0x8892;
const GLenum ELEMENT_ARRAY_BUFFER           = 0x8893;
// const GLenum ARRAY_BUFFER_BINDING           = 0x8894;	
// const GLenum ELEMENT_ARRAY_BUFFER_BINDING   = 0x8895;
void bindBuffer(GLenum target, //上面
				WebGLBuffer? buffer); //createBuffer
				
// 开辟存储空间,向绑定在target上的缓冲区对象写入数据data
// 下文中的usage参数值
const GLenum STREAM_DRAW  = 0x88E0;//STATIC_DRAW 只会向缓冲区写入一次数据 需要绘制很多次
const GLenum STATIC_DRAW  = 0x88E4;//TREAM_DRAW 只会向缓冲区写入一次数据 需要绘制若干次
const GLenum DYNAMIC_DRAW = 0x88E8;//DYNAMIC_DRAW 会向缓冲区对象中多次写入数据 并绘制很多次
void bufferData(GLenum target,  //上面 target
                BufferSource? data, //data 类型化数组 比如:Float32Array
                GLenum usage); //上面 usage

// 获取由 name 参数指定的 attribute 变量存储地址
GLint getAttribLocation(WebGLProgram program, //program 指定包含顶点或者片元着色器的程序对象
                        DOMString name); //name 获取其存储的 attribute 变量名称,最大长度256字节
// 将数据传给由index参数指定的attribute变量
void vertexAttrib1f(GLuint index, GLfloat x);
void vertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
void vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
void vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
// 接收参数为 Float32Array 数组
void vertexAttrib1fv(GLuint index, Float32List values);
void vertexAttrib2fv(GLuint index, Float32List values);
void vertexAttrib3fv(GLuint index, Float32List values);
void vertexAttrib4fv(GLuint index, Float32List values);


// 数据类型
// vertexAttribPointer 中参数type的取值
const GLenum BYTE                           = 0x1400;
const GLenum UNSIGNED_BYTE                  = 0x1401;
const GLenum SHORT                          = 0x1402;
const GLenum UNSIGNED_SHORT                 = 0x1403;
const GLenum INT                            = 0x1404;
const GLenum UNSIGNED_INT                   = 0x1405;
const GLenum FLOAT                          = 0x1406; //常用

// 将绑定到ARRAY_BUFFER的缓冲区对象分配给index指定的attribute变量
void vertexAttribPointer(GLuint index, //指向attribute变量
                         GLint size, //指定缓冲区中每个顶点分量的个数 xyz的话就3 rgba的话就4
                         GLenum type, //数据格式 见上面的枚举
                         GLboolean normalized, //是否将浮点型数据归一化到[0, 1]或者[-1, 1]区间 false
                         GLsizei stride, //指定相邻两个顶点之间的字节数 FSIZE*5
                         GLintptr offset);//指定缓冲区对象中的偏移量 单位字节 可以利用这个偏移量赋值多个attribute
						 
// 开启index对应的attribute对象
// 开启后不能通过 vertexAttrib[1234]f 传值
void enableVertexAttribArray(GLuint index);//指向attribute变量

// 关闭index对应的attribute对象
void disableVertexAttribArray(GLuint index);//指向attribute变量

// 删除参数buffer表示的缓冲区对象
void deleteBuffer(WebGLBuffer? buffer); //createBuffer

常见的顶点数据

  • uv
  • position
  • normal
  • color
  • indices

创建流程

  • EBO
    • createBuffer创建buffer
    • bindBuffer使用buffer
    • bufferData塞入数据buffer
  • VBO(B是指Buffer 把缓冲区当做一个对象)
    • createBuffer创建buffer
    • bindBuffer使用buffer
    • bufferData塞入数据buffer
    • vertexAttribPointer哪些数据是需要的vertex
    • enableVertexAttribArray 允许使用vertex
  • VAO(A是指Array)
    • createVertexArrayOES()创建Vertex
    • createBuffer创建buffer
    • bindVertexArrayOES使用Vertex
    • bindBuffer使用buffer
    • bufferData塞入数据buffer
    • vertexAttribPointer哪些数据是需要的Vertex
    • enableVertexAttribArray 允许使用Vertex

使用流程

  • VBO
    • bindBuffer使用Buffer
    • bindBuffer使用Buffer
    • vertexAttribPointer哪些数据是需要的vertex
  • VAO
    • bindVertexArrayOES使用Vertex

简单的示例

WebGL1.0

  • glsl
attribute vec3 position;
attribute vec2 uv;
attribute vec3 normal;

uniform mat4 model;

varying vec2 vUv;
varying vec3 vNormal;
void main() {
    vUv = uv;
    vNormal = mat3(transpose(inverse(model))) * normal;  
    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
  • 赋值
var vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);
var FSIZE = verticesColors.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(gl.program, "a_Position");
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);
gl.enableVertexAttribArray(a_Position);
var a_Color = gl.getAttribLocation(gl.program, "a_Color");
gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,FSIZE * 6,FSIZE * 3);
gl.enableVertexAttribArray(a_Color);

WebGL2.0

  • glsl
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 uv;

uniform mat4 model;

out vec2 vUv;
out vec3 vNormal;
void main() {
    vUv = uv;
    vNormal = mat3(transpose(inverse(model))) * normal;  
    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}

  • 赋值
const POSITION_LOCATION = 0;
const NORMAL_LOCATION = 1;
const TEXCOORD_0_LOCATION = 2;
glPlaneVAO = gl.createVertexArray();
let planeVBO = gl.createBuffer();
gl.bindVertexArray(glPlaneVAO);
gl.bindBuffer(gl.ARRAY_BUFFER, planeVBO);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(planeVertices), gl.STATIC_DRAW);
gl.enableVertexAttribArray(POSITION_LOCATION);
gl.vertexAttribPointer(POSITION_LOCATION, 3, gl.FLOAT, false, 6 * sizeFloat, 0);
gl.enableVertexAttribArray(NORMAL_LOCATION);
gl.vertexAttribPointer(POSITION_LOCATION, 3, gl.FLOAT, false, 6 * sizeFloat, 3 * sizeFloat);
  • indices
// Indices of the vertices
var indices = new Uint8Array([0,1,2,0,2,3, // front
  0,3,4,0,4,5, // right
  0,5,6,0,6,1, // up
  1,6,7,1,7,2, // left
  7,4,3,7,3,2, // down
  4,7,6,4,6,5 // back
]);
//index的话 必须经过这个api
var indexBuffer = gl.createBuffer(); //index 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); //bind buffer
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); // bufferdata

Uniform

  • glsl里面没有boolean类型,用数字代替
void setBool(const std::string &name, bool value) const
{         
    glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); 
}
  • glsl里面一般很少用int,用贴图的时候用
struct Material {
    sampler2D diffuse;
    vec3 specular;    
    float shininess;
}; 
lightingShader.setInt("material.diffuse", 0);
void setInt(const std::string &name, int value) const
{ 
    glUniform1i(glGetUniformLocation(ID, name.c_str()), value); 
}
  • glsl的数据结构,他对应的opengl API的glGetUniformLocation是Material.ambient等
    • struct 里面不用写uniform
struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;    
    float shininess;
}; 
lightingShader.setVec3("light.ambient", ambientColor);
  • glsl自定义数据结构数组
uniform PointLight pointLights[NR_POINT_LIGHTS];
// directional light
lightingShader.setVec3("dirLight.direction", -0.2f, -1.0f, -0.3f);
lightingShader.setVec3("dirLight.ambient", 0.05f, 0.05f, 0.05f);
lightingShader.setVec3("dirLight.diffuse", 0.4f, 0.4f, 0.4f);
lightingShader.setVec3("dirLight.specular", 0.5f, 0.5f, 0.5f);
// point light 1
lightingShader.setVec3("pointLights[0].position", pointLightPositions[0]);
lightingShader.setVec3("pointLights[0].ambient", 0.05f, 0.05f, 0.05f);
lightingShader.setVec3("pointLights[0].diffuse", 0.8f, 0.8f, 0.8f);
lightingShader.setVec3("pointLights[0].specular", 1.0f, 1.0f, 1.0f);
lightingShader.setFloat("pointLights[0].constant", 1.0f);
lightingShader.setFloat("pointLights[0].linear", 0.09);
lightingShader.setFloat("pointLights[0].quadratic", 0.032);
// point light 2
lightingShader.setVec3("pointLights[1].position", pointLightPositions[1]);
lightingShader.setVec3("pointLights[1].ambient", 0.05f, 0.05f, 0.05f);
lightingShader.setVec3("pointLights[1].diffuse", 0.8f, 0.8f, 0.8f);
lightingShader.setVec3("pointLights[1].specular", 1.0f, 1.0f, 1.0f);
lightingShader.setFloat("pointLights[1].constant", 1.0f);
lightingShader.setFloat("pointLights[1].linear", 0.09);
lightingShader.setFloat("pointLights[1].quadratic", 0.032);
// point light 3
lightingShader.setVec3("pointLights[2].position", pointLightPositions[2]);
lightingShader.setVec3("pointLights[2].ambient", 0.05f, 0.05f, 0.05f);
lightingShader.setVec3("pointLights[2].diffuse", 0.8f, 0.8f, 0.8f);
lightingShader.setVec3("pointLights[2].specular", 1.0f, 1.0f, 1.0f);
lightingShader.setFloat("pointLights[2].constant", 1.0f);
lightingShader.setFloat("pointLights[2].linear", 0.09);
lightingShader.setFloat("pointLights[2].quadratic", 0.032);
// point light 4
lightingShader.setVec3("pointLights[3].position", pointLightPositions[3]);
lightingShader.setVec3("pointLights[3].ambient", 0.05f, 0.05f, 0.05f);
lightingShader.setVec3("pointLights[3].diffuse", 0.8f, 0.8f, 0.8f);
lightingShader.setVec3("pointLights[3].specular", 1.0f, 1.0f, 1.0f);
lightingShader.setFloat("pointLights[3].constant", 1.0f);
lightingShader.setFloat("pointLights[3].linear", 0.09);
lightingShader.setFloat("pointLights[3].quadratic", 0.032);

// ------------------------------------------------------------------------
uniform vec3 viewPos;
void setFloat(const std::string &name, float value) const
{ 
    glUniform1f(glGetUniformLocation(ID, name.c_str()), value); 
}
// ------------------------------------------------------------------------
uniform vec2 viewPos;
void setVec2(const std::string &name, const glm::vec2 &value) const
{ 
    glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); 
}
void setVec2(const std::string &name, float x, float y) const
{ 
    glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); 
}
// ------------------------------------------------------------------------
uniform vec3 viewPos;
void setVec3(const std::string &name, const glm::vec3 &value) const
{ 
    glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); 
}
void setVec3(const std::string &name, float x, float y, float z) const
{ 
    glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); 
}
// ------------------------------------------------------------------------
uniform vec4 viewPos;
void setVec4(const std::string &name, const glm::vec4 &value) const
{ 
    glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); 
}
void setVec4(const std::string &name, float x, float y, float z, float w) const
{ 
    glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); 
}
// ------------------------------------------------------------------------
uniform mat2 projection;
void setMat2(const std::string &name, const glm::mat2 &mat) const
{
    glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
// ------------------------------------------------------------------------
uniform mat3 projection;
void setMat3(const std::string &name, const glm::mat3 &mat) const
{
    glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
// ------------------------------------------------------------------------
uniform mat4 projection;
void setMat4(const std::string &name, const glm::mat4 &mat) const
{
    glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}