- 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
小行星带效果渲染:
这里还有点问题,需要再调试一下。
网友评论