i was trying to develop a test case for instanced rendering. I am trying to render multiple cubes using glDrawArraysInstanced() as well as glDrawArrays().
but the offset values passed in glDrawArraysInstanced() do not give required output as obtained incase of rendering with glDrawArrays().
here is the code snippet as well as the shader code used.
if(!INSTANCE_RENDERING) { for(int j=0;j<INSTANCE;j++) { glUniform3f(offLocation, offset[n], offset[n+1], offset[n+2]); Matrix modelView = Matrix::createRotationXYZ(angle+i, angle+i, angle+i); glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, modelView.getAsArray()); glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (void*)0); if(offset[n] > th || offset[n+0] < -1*th) {dir[n+0] = -1* dir[n+0]; } if(offset[n+1] > th || offset[n+1] < -1*th) {dir[n+1] = -1 *dir[n+1];} offset[n] += dir[n]; offset[n+1] += dir[n+1]; offset[n+2] += dir[n+2]; n +=3; } //glClearColor(0.0f, 0.0f, 0.0f, 1.0f); } else //instance rendering enabled { glUniform3f(offLocation, offset[n], offset[n+1], offset[n+2]); Matrix modelView = Matrix::createRotationXYZ(angle+i, angle+i, angle+i); glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, modelView.getAsArray()); glDrawElementsInstanced ( GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, ( const void * )0, INSTANCE ); if(offset[n] > th || offset[n+0] < -1*th) {dir[n+0] = -1* dir[n+0]; } if(offset[n+1] > th || offset[n+1] < -1*th) {dir[n+1] = -1 *dir[n+1];} offset[n] += dir[n]; offset[n+1] += dir[n+1]; offset[n+2] += dir[n+2]; n +=3; }
shader source code
// Fragment and vertex shaders code std::string str = " precision mediump float;\ varying vec4 vColor;\ void main(void) {\ gl_FragColor = vColor;\ }"; const char *pszFragShader = str.c_str(); std::string str2 = "precision highp float;\ attribute vec3 aVertexPosition;\ attribute vec4 aVertexColor;\ uniform mat4 uMVMatrix;\ uniform mat4 uPMatrix;\ varying vec4 vColor;\ uniform vec3 aOffsetPosition;\ vec4 position;\ void main(void) {\ position = vec4(aVertexPosition, 1.0)+ vec4(aOffsetPosition, 45.0) ; \ gl_Position = uPMatrix * position;\ vColor = aVertexColor;\ }";
The issue is that you are not doing anything with the instancing information. You are telling OpenGL ES you want to draw multiple instances, but every instance is being transformed identically. Your shader (simplified example below) applies the same transform to every instance, using the same transformation matrix - they are all going to look identical.
precision highp float; attribute vec4 aVertexPosition; uniform mat4 uMVPMatrix; void main(void) { gl_Position = uMVPMatrix * aVertexPosition; }
You need to give the shader different state for each instance, which is done by passing an array of inputs - in the example below we change the model-view-projection matrix - and indexing into that array using gl_InstanceID in the shader. So you want something like:
precision highp float; attribute vec4 aVertexPosition; uniform mat4 uMVPMatrix[INSTANCES]; void main(void) { gl_Position = uMVPMatrix[gl_InstanceID] * aVertexPosition; }
HTH, Pete
Thanks alot for the suggestions. i tried but couldnt get through. i made some modifications in the code and now i could render only one cube with all transformations required. can you guide me why mutiple cubes are not being rendered?
#include <math.h>
#include "Timer.h"
//#include <sys/time.h>
#include <time.h>
//#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <string>
#include "win_process.h"
#include "Matrix.h"
#define EGL_EGLEXT_PROTOTYPES 1
#define GL_GLEXT_PROTOTYPES 1
#include "GLES3/gl3.h"
#include "GLES3/gl3ext.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"
using namespace std;
#define INSTANCE_RENDERING 1
#define WINDOW_W 1920
#define WINDOW_H 1080
unsigned int uiWidth = WINDOW_W;
unsigned int uiHeight = WINDOW_H;
int INSTANCE = 1000;
extern EGLDisplay sEGLDisplay;
extern EGLContext sEGLContext;
extern EGLSurface sEGLSurface;
double rand2()
{
return (double)rand() / (double)RAND_MAX ;
}
int InstanceRendering (void)
//printf("Enter INSTANCE :");
//scanf("%d",&INSTANCE);
// Fragment and vertex shaders code
std::string str = " precision mediump float;\
varying vec4 vColor;\
void main(void) {\
gl_FragColor = vColor;\
}";
const char *pszFragShader = str.c_str();
std::string str2 = "precision highp float;\
attribute vec3 aVertexPosition;\
attribute vec4 aVertexColor;\
uniform mat4 uMVMatrix;\
uniform mat4 uPMatrix;\
uniform vec3 aOffsetPosition;\
vec4 position;\
position = vec4(aVertexPosition, 1.0)+ vec4(aOffsetPosition, 45.0)
gl_Position = uPMatrix * position;\
vColor = aVertexColor;\
const char *pszVertShader = str2.c_str();
GLuint uiFragShader, uiVertShader;
GLuint uiProgramObject;
uiFragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(uiFragShader, 1, &pszFragShader, NULL);
glCompileShader(uiFragShader);
GLint bShaderCompiled;
glGetShaderiv(uiFragShader, GL_COMPILE_STATUS, &bShaderCompiled);
if (!bShaderCompiled)
int i32InfoLogLength, i32CharsWritten;
glGetShaderiv(uiFragShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
char* pszInfoLog = new char[i32InfoLogLength];
glGetShaderInfoLog(uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
printf("********FragmentShader %s\n", pszInfoLog);
delete[] pszInfoLog;
uiVertShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(uiVertShader, 1, (const char**)&pszVertShader, NULL);
glCompileShader(uiVertShader);
glGetShaderiv(uiVertShader, GL_COMPILE_STATUS, &bShaderCompiled);
glGetShaderiv(uiVertShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
glGetShaderInfoLog(uiVertShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
printf("********VertexShader %s\n", pszInfoLog);
uiProgramObject = glCreateProgram();
glAttachShader(uiProgramObject, uiFragShader);
glAttachShader(uiProgramObject, uiVertShader);
glLinkProgram(uiProgramObject);
GLint bLinked;
glGetProgramiv(uiProgramObject, GL_LINK_STATUS, &bLinked);
if (!bLinked)
glGetProgramiv(uiProgramObject, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
glGetProgramInfoLog(uiProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
printf("%s",pszInfoLog);
glUseProgram(uiProgramObject);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GLfloat vertexPositionData[] = {
// Front face
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Top face
// Bottom face
// Right face
// Left face
-1.0, 1.0, -1.0
};
GLuint posVbo;
glGenBuffers(1, &posVbo);
glBindBuffer(GL_ARRAY_BUFFER, posVbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositionData), vertexPositionData, GL_STATIC_DRAW);
GLfloat fragPositionData[] = {
0.583f, 0.771f, 0.014f,1.0,
0.609f, 0.115f, 0.436f,1.0,
0.327f, 0.483f, 0.844f,1.0,
0.822f, 0.569f, 0.201f,1.0,
0.435f, 0.602f, 0.223f,1.0,
0.310f, 0.747f, 0.185f,1.0,
0.597f, 0.770f, 0.761f,1.0,
0.559f, 0.436f, 0.730f,1.0,
0.359f, 0.583f, 0.152f,1.0,
0.483f, 0.596f, 0.789f,1.0,
0.559f, 0.861f, 0.639f,1.0,
0.195f, 0.548f, 0.859f,1.0,
0.014f, 0.184f, 0.576f,1.0,
0.771f, 0.328f, 0.970f,1.0,
0.406f, 0.615f, 0.116f,1.0,
0.676f, 0.977f, 0.133f,1.0,
0.971f, 0.572f, 0.833f,1.0,
0.140f, 0.616f, 0.489f,1.0,
0.997f, 0.513f, 0.064f,1.0,
0.945f, 0.719f, 0.592f,1.0,
0.543f, 0.021f, 0.978f,1.0,
0.279f, 0.317f, 0.505f,1.0,
0.167f, 0.620f, 0.077f,1.0,
0.347f, 0.857f, 0.137f,1.0
/* 1.0, 0.0, 0.0, 1.0, // Front face
1.0, 0.0, 0.0, 1.0, // Front face
1.0, 1.0, 0.0, 1.0, // Back face
0.0, 1.0, 0.0, 1.0, // Top face
1.0, 0.5, 0.5, 1.0, // Bottom face
1.0, 0.0, 1.0, 1.0, // Right face
0.0, 0.0, 1.0, 1.0, // Left face
0.0, 0.0, 1.0, 1.0, // Left face */
GLuint fragVbo;
glGenBuffers(1, &fragVbo);
glBindBuffer(GL_ARRAY_BUFFER, fragVbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(fragPositionData), fragPositionData, GL_STATIC_DRAW);
unsigned short cubeVertexIndices[] = {
0, 1, 2, 0, 2, 3, // Front face
4, 5, 6, 4, 6, 7, // Back face
8, 9, 10, 8, 10, 11, // Top face
12, 13, 14, 12, 14, 15, // Bottom face
16, 17, 18, 16, 18, 19, // Right face
20, 21, 22, 20, 22, 23 // Left face
GLuint idxVbo;
glGenBuffers(1, &idxVbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idxVbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeVertexIndices), cubeVertexIndices, GL_STATIC_DRAW);
printf("**********Number of Instances for glDrawElements----%d\n", INSTANCE);
int m =0; int t=0;
float offset[1000*3];
float dir[1000*3];
int angle =0;
for(int i=0;i<INSTANCE;i++)
offset[m++]= 0.0f;
double xi[1000], yi[1000], zi[1000];
double z = rand2();
if(z > 0.40) { z = 0.38;}
if(z < 0.11) z = 0.30;
z = -1*z*100;
zi[i] = -80;
xi[i] = zi[i]/2;
double y = rand2();
double x = rand2();
if(x < 0.5) {x = zi[i] * x *2; }
else x = zi[i] * x;
if(rand2() <0.5) {xi[i] = -1*x;}
else xi[i] = x;
if(y >0.5) {y = zi[i]*y;}
else {y = 2*y*zi[i];}
if(rand2() <0.5) {yi[i] = -1*y;}
else yi[i] = y;
dir[t++] = xi[i]/(z*10);
dir[t++] = yi[i]/(z*10);
dir[t++] =0.0;
Timer fpsTimer;
fpsTimer.reset();
glViewport(0, 0, uiWidth,uiHeight);
glClear(GL_COLOR_BUFFER_BIT);
Matrix perspective = Matrix::matrixPerspective(45.0f, (float)uiWidth/(float)uiHeight, 0.1f, 100.0f);
int MVLocation = glGetUniformLocation(uiProgramObject, "uMVMatrix");
glUniformMatrix4fv(MVLocation, 1, GL_FALSE, perspective.getAsArray());
int positionLocation = glGetAttribLocation(uiProgramObject, "aVertexPosition");
glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
int colorLocation = glGetAttribLocation(uiProgramObject, "aVertexColor");
glEnableVertexAttribArray(colorLocation);
glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
int offLocation = glGetUniformLocation(uiProgramObject, "aOffsetPosition");
int matrixLocation = glGetUniformLocation(uiProgramObject, "uPMatrix");
for(int i=0 ; i<1000;i++){
int n=0;
int th = 40;
float fFPS = fpsTimer.getFPS();
if(fpsTimer.isTimePassed(1.0f))
printf("FPS: %f\n", fFPS);
if(!INSTANCE_RENDERING)
for(int j=0;j<INSTANCE;j++)
glUniform3f(offLocation, offset[n], offset[n+1], offset[n+2]);
Matrix modelView = Matrix::createRotationXYZ(angle+i, angle+i, angle+i);
glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, modelView.getAsArray());
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (void*)0);
if(offset[n] > th || offset[n+0] < -1*th) {dir[n+0] = -1* dir[n+0]; }
if(offset[n+1] > th || offset[n+1] < -1*th) {dir[n+1] = -1 *dir[n+1];}
offset[n] += dir[n];
offset[n+1] += dir[n+1];
offset[n+2] += dir[n+2];
n +=3;
//glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
else //instance rendering enabled
glDrawElementsInstanced ( GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, ( const void * )0, INSTANCE );
eglSwapBuffers(sEGLDisplay, sEGLSurface);
// Frees the OpenGL handles for the program and the 2 shaders
glDeleteProgram(uiProgramObject);
glDeleteShader(uiFragShader);
glDeleteShader(uiVertShader);
// Delete the VBO as it is no longer needed
glDeleteBuffers(1, &posVbo);
glDeleteBuffers(1, &idxVbo);
return 0;
Hi Shanksanghoi,
In your latest code above, your gl_Position is still being worked out as
This needs to be changed, otherwise each of the instanced meshes will be transformed exactly the same, and only one model will appear to be drawn. Pete's last response above has an example
Thanks,
Chris
What exactly have you tried ? Twice now Pete has pointed out the exact cause of the issue and if you take a look at instancing ( cursory Google search ) it would be evident exactly what the issues is. In order to use instancing I would suggest reading the specification or some other resource that explains exactly how instancing works. Just trying to fish out the exact answer without doing any work does not help in the long run...understanding the basics will be of more help since you will be able to reason more about the potential cause of the issue you are currently having. I don't want to speak for Pete, but I think he was leaning more towards you taking his suggestion and actually investigating the cause of the issue. Chris has narrowed it down, so let see if that works for you.
The bottom line like Chris and Pete pointed out is that you are not using anything to differentiate between the different instances being rendered. The shader has to have a way of knowing that transform x or color c is for instance n. The shader you posted is using the same transform for all instances which will cause them to be rendered in the same location onscreen.