在WebGL中绘制多种形状

在WebGL中绘制多种形状,webgl,Webgl,我在读学校的教程 var-gl; 函数initGL(){ //获取WebGL上下文 var canvas=document.getElementById(“canvas”); gl=getWebGLContext(画布); 如果(!gl){ 返回; } } 变量位置; var分解定位; var颜色定位; var转换定位; 变量旋转定位; var换算=[50,50]; 变量旋转=[0,1]; var角=0; 函数initShaders(){ //安装GLSL程序 vertexShader=cre

我在读学校的教程


var-gl;
函数initGL(){
//获取WebGL上下文
var canvas=document.getElementById(“canvas”);
gl=getWebGLContext(画布);
如果(!gl){
返回;
}
}
变量位置;
var分解定位;
var颜色定位;
var转换定位;
变量旋转定位;
var换算=[50,50];
变量旋转=[0,1];
var角=0;
函数initShaders(){
//安装GLSL程序
vertexShader=createShaderFromScriptElement(gl,“2d顶点着色器”);
fragmentShader=createShaderFromScriptElement(gl,“2d片段着色器”);
program=createProgram(gl,[vertexShader,fragmentShader]);
gl.useProgram(程序);
//查找顶点数据需要去的地方。
positionLocation=gl.GetAttriblLocation(程序,“a_位置”);
//查找制服
resolutionLocation=gl.getUniformLocation(程序,“u_分辨率”);
colorLocation=gl.getUniformLocation(程序,“u_颜色”);
translationLocation=gl.getUniformLocation(程序,“u_翻译”);
rotationLocation=gl.getUniformLocation(程序,“u_旋转”);
//制定决议
gl.uniform2f(分辨率位置、画布宽度、画布高度);
}
函数initBuffers(){
//创建一个缓冲区。
var buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY\u BUFFER,BUFFER);
gl.EnableVertexAttributeArray(位置位置);
gl.VertexAttribute指针(位置位置,2,gl.FLOAT,false,0,0);
//设置几何图形。
集合几何(gl);
}
功能设置颜色(红色、绿色、蓝色){
gl.uniform4f(颜色位置,红色、绿色、蓝色,1);
}
//画场景。
函数drawsecene(){
//清理画布。
总账清除(总账颜色缓冲位);
//设置翻译。
gl.uniform2fv(翻译位置,翻译);
//设置旋转。
gl.uniform2fv(旋转位置,旋转);
//绘制几何图形。
gl.绘图阵列(gl.三角形,0,6);
}
//用定义字母“F”的值填充缓冲区。
函数集几何(gl){
/*假设声明了size1*/
变量顶点=[
-尺寸1/2,-尺寸1/2,
-尺寸1/2,尺寸1/2,
尺寸1/2,尺寸1/2,
尺寸1/2,尺寸1/2,
尺寸1/2,-尺寸1/2,
-尺寸1/2,-尺寸1/2];
缓冲数据(
gl.ARRAY\u缓冲区,
新的浮点数组(顶点),
gl.静态(U形图);
}
函数animate(){
平移[0]+=0.01;
翻译[1]+=0.01;
角度+=0.01;
旋转[0]=数学cos(角度);
旋转[1]=数学sin(角度);
}
函数tick(){
请求帧(勾号);
drawScene();
制作动画();
}
函数start(){
initGL();
initShaders();
initBuffers();
setColor(0.2,0.5,0.5);
勾选();
}
属性向量2 a_位置;
均匀vec2u_分辨率;
统一vec2u_翻译;
均匀vec2u_旋转;
void main(){
vec2旋转位置=vec2(
a_位置.x*u旋转.y+a_位置.y*u旋转.x,
a_位置.y*u旋转.y-a_位置.x*u旋转.x);
//加上翻译。
vec2位置=旋转位置+u_平移;
//将位置从像素转换为0.0到1.0
vec2 zeroToOne=位置/u_分辨率;
//从0->1转换为0->2
vec2 zeroToTwo=zeroToOne*2.0;
//从0->2转换为-1->+1(剪辑空间)
vec2 clipSpace=zeroToTwo-1.0;
gl_位置=vec4(clipSpace,0,1);
}
精密中泵浮子;
均匀的vec4 u_颜色;
void main(){
gl_FragColor=u_颜色;
}
我的1号形状WebGL程序的工作原理如下:

  • 从canvas元素获取上下文(gl)
  • 使用对象的形状初始化缓冲区
  • drawsecene()
    :调用
    gl.drawArrays()
  • 如果有动画,一个更新函数,它更新我的形状的角度、位置, 然后在
    tick()
    中同时调用
    drawsecene()
    ,以便重复调用它
  • 现在,当我需要一个以上的形状时,我是否应该一次用多个对象填充单个缓冲区,然后使用它稍后调用
    drawsecene()
    一次绘制所有对象 [或]
    我是否应该重复调用
    requestAnimFrame()

    中的
    initBuffer
    drawsecene()
    ,在一个缓冲区中使用多个网格(并按照您的建议使用单个
    gl.drawArrays()
    渲染它们)在复杂场景中产生更好的性能,但显然在这一点上,您无法更改每个网格的着色器统一(例如变换)


    如果要使网格独立运行,则必须分别渲染每个网格。您仍然可以将所有网格保留在一个缓冲区中,以避免调用
    gl.bindBuffer()
    时产生的一些开销,但这不会有多大帮助,至少在简单场景中不会如此。

    为场景中想要的每个对象分别创建缓冲区,否则它们将无法单独移动和使用着色器效果

    但这是为了防止对象不同。从我这里得到的信息来看,我想你只是想在不同的位置上多次绘制相同的形状,对吗

    这样做的方法是,在第一次绘制形状后,使用不同的平移矩阵将
    translationLocation
    设置为一致。这样,当您再次绘制形状时,它将位于其他位置,而不是位于另一个形状的顶部,以便您可以看到它。您可以以不同的方式设置所有这些转换矩阵,然后只需再次调用
    gl.drawerelements
    ,因为您将绘制已经在使用的相同缓冲区。

    在伪代码中

    在初始时间

    • 从canvas元素获取上下文(gl)
    • 对于每个着色器
      • 创建着色器
      • 查找属性和统一位置
    • 对于每个形状
      • 使用形状初始化缓冲区
    • 对于每个纹理
        <script class = "WebGL">
        var gl;
        function initGL() {
          // Get A WebGL context
          var canvas = document.getElementById("canvas");
          gl = getWebGLContext(canvas);
          if (!gl) {
            return;
          }
        }
        var positionLocation;
        var resolutionLocation;
        var colorLocation;
        var translationLocation;
        var rotationLocation;
        var translation = [50,50];
        var rotation = [0, 1];
        var angle = 0;
        function initShaders() {
          // setup GLSL program
          vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
          fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
          program = createProgram(gl, [vertexShader, fragmentShader]);
          gl.useProgram(program);
        
          // look up where the vertex data needs to go.
          positionLocation = gl.getAttribLocation(program, "a_position");
        
          // lookup uniforms
          resolutionLocation = gl.getUniformLocation(program, "u_resolution");
          colorLocation = gl.getUniformLocation(program, "u_color");
          translationLocation = gl.getUniformLocation(program, "u_translation");
            rotationLocation = gl.getUniformLocation(program, "u_rotation");
        
          // set the resolution
          gl.uniform2f(resolutionLocation, canvas.width, canvas.height);
        }
        function initBuffers() {
          // Create a buffer.
          var buffer = gl.createBuffer();
          gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
          gl.enableVertexAttribArray(positionLocation);
          gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
        
          // Set Geometry.
          setGeometry(gl);
        }
        
        function setColor(red, green, blue) {
            gl.uniform4f(colorLocation, red, green, blue, 1);
        }
        // Draw the scene.
        function drawScene() {
            // Clear the canvas.
            gl.clear(gl.COLOR_BUFFER_BIT);
        
            // Set the translation.
            gl.uniform2fv(translationLocation, translation);
            // Set the rotation.
            gl.uniform2fv(rotationLocation, rotation);
        
            // Draw the geometry.
            gl.drawArrays(gl.TRIANGLES, 0, 6);
        }
        
        
        // Fill the buffer with the values that define a letter 'F'.
        function setGeometry(gl) {
        /*Assume size1 is declared*/
            var vertices = [
                 -size1/2, -size1/2,
                 -size1/2, size1/2,
                 size1/2, size1/2,
                 size1/2, size1/2,
                 size1/2, -size1/2,
                 -size1/2, -size1/2 ];
              gl.bufferData(
                 gl.ARRAY_BUFFER,
                 new Float32Array(vertices),
                 gl.STATIC_DRAW);
        }
        function animate() {
            translation[0] += 0.01;
            translation[1] += 0.01;
            angle += 0.01;
            rotation[0] = Math.cos(angle);
            rotation[1] = Math.sin(angle);
        }
        function tick() {
            requestAnimFrame(tick);
            drawScene();
            animate();
        }
        function start() {
        
            initGL();
            initShaders();
            initBuffers();
            setColor(0.2, 0.5, 0.5);
            tick();
        }
        
        </script>
        
        <!-- vertex shader -->
        <script id="2d-vertex-shader" type="x-shader/x-vertex">
            attribute vec2 a_position;
        
            uniform vec2 u_resolution;
            uniform vec2 u_translation;
            uniform vec2 u_rotation;
            void main() {
                vec2 rotatedPosition = vec2(
                a_position.x * u_rotation.y + a_position.y * u_rotation.x,
                a_position.y * u_rotation.y - a_position.x * u_rotation.x);
        
               // Add in the translation.
               vec2 position = rotatedPosition + u_translation;
        
               // convert the position from pixels to 0.0 to 1.0
               vec2 zeroToOne = position / u_resolution;
        
               // convert from 0->1 to 0->2
               vec2 zeroToTwo = zeroToOne * 2.0;
        
               // convert from 0->2 to -1->+1 (clipspace)
               vec2 clipSpace = zeroToTwo - 1.0;
        
               gl_Position = vec4(clipSpace, 0, 1);
            }
        </script>
        <!-- fragment shader -->
        <script id="2d-fragment-shader" type="x-shader/x-fragment">
            precision mediump float;
        
            uniform vec4 u_color;
        
            void main() {
               gl_FragColor = u_color;
            }
        </script>