in teapots/more-teapots/src/main/cpp/MoreTeapotsRenderer.cpp [47:198]
void MoreTeapotsRenderer::Init(const int32_t numX, const int32_t numY,
const int32_t numZ) {
if (ndk_helper::GLContext::GetInstance()->GetGLVersion() >= 3.0) {
geometry_instancing_support_ = true;
} else if (ndk_helper::GLContext::GetInstance()->CheckExtension(
"GL_NV_draw_instanced") &&
ndk_helper::GLContext::GetInstance()->CheckExtension(
"GL_NV_uniform_buffer_object")) {
LOGI("Supported via extension!");
//_bGeometryInstancingSupport = true;
//_bARBSupport = true; //Need to patch shaders
// Currently this has been disabled
}
// Settings
glFrontFace(GL_CCW);
// Create Index buffer
num_indices_ = sizeof(teapotIndices) / sizeof(teapotIndices[0]);
glGenBuffers(1, &ibo_);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(teapotIndices), teapotIndices,
GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Create VBO
num_vertices_ = sizeof(teapotPositions) / sizeof(teapotPositions[0]) / 3;
int32_t stride = sizeof(TEAPOT_VERTEX);
int32_t index = 0;
TEAPOT_VERTEX* p = new TEAPOT_VERTEX[num_vertices_];
for (int32_t i = 0; i < num_vertices_; ++i) {
p[i].pos[0] = teapotPositions[index];
p[i].pos[1] = teapotPositions[index + 1];
p[i].pos[2] = teapotPositions[index + 2];
p[i].normal[0] = teapotNormals[index];
p[i].normal[1] = teapotNormals[index + 1];
p[i].normal[2] = teapotNormals[index + 2];
index += 3;
}
glGenBuffers(1, &vbo_);
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
glBufferData(GL_ARRAY_BUFFER, stride * num_vertices_, p, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
delete[] p;
// Init Projection matrices
teapot_x_ = numX;
teapot_y_ = numY;
teapot_z_ = numZ;
vec_mat_models_.reserve(teapot_x_ * teapot_y_ * teapot_z_);
UpdateViewport();
const float total_width = 500.f;
float gap_x = total_width / (teapot_x_ - 1);
float gap_y = total_width / (teapot_y_ - 1);
float gap_z = total_width / (teapot_z_ - 1);
float offset_x = -total_width / 2.f;
float offset_y = -total_width / 2.f;
float offset_z = -total_width / 2.f;
for (int32_t x = 0; x < teapot_x_; ++x)
for (int32_t y = 0; y < teapot_y_; ++y)
for (int32_t z = 0; z < teapot_z_; ++z) {
vec_mat_models_.push_back(ndk_helper::Mat4::Translation(
x * gap_x + offset_x, y * gap_y + offset_y,
z * gap_z + offset_z));
vec_colors_.push_back(ndk_helper::Vec3(
random() / float(RAND_MAX * 1.1), random() / float(RAND_MAX * 1.1),
random() / float(RAND_MAX * 1.1)));
float rotation_x = random() / float(RAND_MAX) - 0.5f;
float rotation_y = random() / float(RAND_MAX) - 0.5f;
vec_rotations_.push_back(ndk_helper::Vec2(rotation_x * 0.05f, rotation_y * 0.05f));
vec_current_rotations_.push_back(
ndk_helper::Vec2(rotation_x * M_PI, rotation_y * M_PI));
}
if (geometry_instancing_support_) {
//
// Create parameter dictionary for shader patch
std::map<std::string, std::string> param;
param[std::string("%NUM_TEAPOT%")] =
ToString(teapot_x_ * teapot_y_ * teapot_z_);
param[std::string("%LOCATION_VERTEX%")] = ToString(ATTRIB_VERTEX);
param[std::string("%LOCATION_NORMAL%")] = ToString(ATTRIB_NORMAL);
if (arb_support_)
param[std::string("%ARB%")] = std::string("ARB");
else
param[std::string("%ARB%")] = std::string("");
// Load shader
bool b = LoadShadersES3(&shader_param_, "Shaders/VS_ShaderPlainES3.vsh",
"Shaders/ShaderPlainES3.fsh", param);
if (b) {
//
// Create uniform buffer
//
GLuint bindingPoint = 1;
GLuint blockIndex;
blockIndex = glGetUniformBlockIndex(shader_param_.program_, "ParamBlock");
glUniformBlockBinding(shader_param_.program_, blockIndex, bindingPoint);
// Retrieve array stride value
int32_t num_indices;
glGetActiveUniformBlockiv(shader_param_.program_, blockIndex,
GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num_indices);
GLint i[num_indices];
GLint stride[num_indices];
glGetActiveUniformBlockiv(shader_param_.program_, blockIndex,
GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, i);
glGetActiveUniformsiv(shader_param_.program_, num_indices, (GLuint*)i,
GL_UNIFORM_ARRAY_STRIDE, stride);
ubo_matrix_stride_ = stride[0] / sizeof(float);
ubo_vector_stride_ = stride[2] / sizeof(float);
glGenBuffers(1, &ubo_);
glBindBuffer(GL_UNIFORM_BUFFER, ubo_);
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, ubo_);
// Store color value which wouldn't be updated every frame
int32_t size = teapot_x_ * teapot_y_ * teapot_z_ *
(ubo_matrix_stride_ + ubo_matrix_stride_ +
ubo_vector_stride_); // Mat4 + Mat4 + Vec3 + 1 stride
float* pBuffer = new float[size];
float* pColor =
pBuffer + teapot_x_ * teapot_y_ * teapot_z_ * ubo_matrix_stride_ * 2;
for (int32_t i = 0; i < teapot_x_ * teapot_y_ * teapot_z_; ++i) {
memcpy(pColor, &vec_colors_[i], 3 * sizeof(float));
pColor += ubo_vector_stride_; // Assuming std140 layout which is 4
// DWORD stride for vectors
}
glBufferData(GL_UNIFORM_BUFFER, size * sizeof(float), pBuffer,
GL_DYNAMIC_DRAW);
delete[] pBuffer;
} else {
LOGI("Shader compilation failed!! Falls back to ES2.0 pass");
// This happens some devices.
geometry_instancing_support_ = false;
// Load shader for GLES2.0
LoadShaders(&shader_param_, "Shaders/VS_ShaderPlain.vsh",
"Shaders/ShaderPlain.fsh");
}
} else {
// Load shader for GLES2.0
LoadShaders(&shader_param_, "Shaders/VS_ShaderPlain.vsh",
"Shaders/ShaderPlain.fsh");
}
}