实例化

  • 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

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

这一节需要好好回顾。

你可能感兴趣的:(实例化)