实例化

作者: 一毛钱 | 来源:发表于2020-03-28 22:33 被阅读0次
    • 1、能够将数据一次性发送给GPU,然后使用一个绘制函数让OpenGL利用这些数据绘制多个物体,就会更方便了。这就是实例化
    • 2、绘制个数并没有上限,只是我的个数设置存在问题,我需要设置V3有400个,然后才能绘制出200个四边形。 应该是那个值设置错误了。
    • 3、绑定定点数组,上传数据后,需要设置glVertexAttribDivisor(offLocation, 1);//第一个元素是属性数组下标m,第二个元素时除数,
      隔多少个更新一次下标。1代表绘制一个元素更新一次。
      告诉OpenGL该什么时候更新定点属性的内容到新一数组,第一个参数是定点属性,第二个参数是属性除数,默认为0.
    • 4、实际绘制时调用,glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 200); 最后一个参数,代表绘制实力的个数,200个四边形。
    • 5、实例化数组。

    绘制多个四边形案例:

    //顶点着色器
    attribute vec2 aPos;
    attribute vec3 fragColor;
    attribute vec3 offsets;
    
    uniform mat4 projectionM;
    uniform mat4 modelViewM;
    
    
    
    varying lowp vec3 outTextCoord;
    
    void main(){
        outTextCoord = fragColor;
        vec2 pos = aPos * (offsets.z/200.0);//z是通过数组传递进来的
        gl_Position = projectionM * modelViewM * vec4(pos.x+offsets.x,pos.y+offsets.y,0,1.0);
        //gl_Position = projectionM * modelViewM * vec4(aPos.x+offsets.x,aPos.y+offsets.y,0,1.0);
        //gl_Position = projectionM * modelViewM * vec4(aPos.x + gl_InstanceID*0.1,aPos.y*gl_InstanceID*0.1,0,1.0);
    }
    
    //加载VA0
    - (GLuint)loadVAOAndVBO{
        
        KSVec3 v3[400];
        int index = 0;
        float offset = 0.1f;
        for (int y = -20; y < 20; y += 2)
        {
            for (int x = -10; x < 10; x += 1)
            {
                KSVec3 translation;
                translation.x = (float)x / 10.0f + offset;
                translation.y = (float)y / 10.0f + offset;
                translation.z = index;
                v3[index++] = translation;
            }
        }
        
        //将数据上传到着色器
        GLuint offPInt;
        glGenBuffers(1, &offPInt);
        glBindBuffer(GL_ARRAY_BUFFER, offPInt);
        glBufferData(GL_ARRAY_BUFFER, sizeof(v3), &v3[0], GL_DYNAMIC_DRAW);
        
        GLuint VAO,VBO;
        glGenVertexArrays(1, &VAO);
        
        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBindVertexArray(VAO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_DYNAMIC_DRAW);
        
        GLuint aposId = glGetAttribLocation(self.myProgram, "aPos");
        GLuint textCoordId = glGetAttribLocation(self.myProgram, "fragColor");
        glVertexAttribPointer(aposId, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), NULL);
        glVertexAttribPointer(textCoordId, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), NULL+2*(sizeof(GLfloat)));
        glEnableVertexAttribArray(aposId);
        glEnableVertexAttribArray(textCoordId);
        
        GLuint offLocation = glGetAttribLocation(self.myProgram, "offsets");
        glBindBuffer(GL_ARRAY_BUFFER, offPInt);
        glVertexAttribPointer(offLocation, 3, GL_FLOAT, GL_FALSE, 3*sizeof(CGFloat), NULL);
        glEnableVertexAttribArray(offLocation);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    //设置除数,每次渲染一个实例更新一下该属性,所以设置成1.
        glVertexAttribDivisor(offLocation, 1);
        
        return VAO;
    }
    
    // 渲染
    - (void)render{
        
        [ZKLodaShader glCheckError];
        glEnable(GL_DEPTH_TEST);
        glClearColor(0.5, 0.5, 0, 1);
        glClearDepthf(1.0);
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        
        if (!self.myProgram) {
           self.myProgram = [self loadShader];
        }
        
        if (self.myProgram) {
            glUseProgram(self.myProgram);
        } else {
            NSLog(@"着色器程序为空--- ");
            return ;
        }
        [ZKLodaShader glCheckError];
        GLuint VAO = [self loadVAOAndVBO];
        [ZKLodaShader glCheckError];
        glViewport(0, 0, _viewWidth, _viewHeight);
       
        //设置变换
       GLuint projMId = glGetUniformLocation(self.myProgram, "projectionM");
       GLuint modlMId = glGetUniformLocation(self.myProgram, "modelViewM");
        
        KSMatrix4 projM,modelViewM;
        
        ksMatrixLoadIdentity(&projM);
        ksMatrixLoadIdentity(&modelViewM);
        [ZKLodaShader glCheckError];
        ksPerspective(&projM, 45, (_viewWidth*1.0)/(_viewHeight*1.0), 0.1, 100);
        //ksOrtho(&projM, -1, 1, -1, 1, 0, 100);
        glUniformMatrix4fv(projMId, 1, GL_FALSE, &projM.m[0][0]);
        
        ksTranslate(&modelViewM, 0, 0, -5);
        _angle += 2;
        //ksRotate(&modelViewM, _angle, 1, 1, 0);
        glUniformMatrix4fv(modlMId, 1, GL_FALSE, &modelViewM.m[0][0]);
        
        [ZKLodaShader glCheckError];
        
        //绘制
        glBindVertexArray(VAO);
        glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 200);
        glBindVertexArray(0);
        glDeleteVertexArrays(1, &VAO);
        [ZKLodaShader glCheckError];
        if (_myColorRenderBuffer) {
            glBindRenderbuffer(GL_RENDERBUFFER, _myColorRenderBuffer);
        }
        
        glBindVertexArray(0);
        glDeleteVertexArrays(1, &VAO);
        [self.myContext presentRenderbuffer:GL_RENDERBUFFER];
    }
    

    效果图:


    实例化渲染.png

    小行星带效果渲染:
    这里还有点问题,需要再调试一下。

    这一节需要好好回顾。

    相关文章

      网友评论

          本文标题:实例化

          本文链接:https://www.haomeiwen.com/subject/xgjeuhtx.html