implement grid and heightmap with lambert shading

This commit is contained in:
2018-12-24 22:22:16 +01:00
parent 4d2706bfab
commit 52c87d9ec6
16 changed files with 297 additions and 101 deletions

View File

@@ -43,11 +43,13 @@ bool Shape::create_buffers_imp(GLvoid* idx, GLvoid* vertices, int isize, int vsi
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, nor));
}
glBindVertexArray(0);
#endif
@@ -81,10 +83,12 @@ bool Shape::create_buffers(GLvoid* vertices, int vsize)
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, nor));
}
glBindVertexArray(0);
#endif
@@ -239,20 +243,29 @@ void Plane::create_impl(float w, float h, int div, GLushort *idx, vertex_t *vert
bool HeightmapPlane::create(float w, float h, const Image& img, float scale)
{
int div = img.width - 1; // TODO: handle height also
Image img_tmp;
glm::u8vec4* px = (glm::u8vec4*)img.data();
glm::vec2 new_size = glm::clamp(glm::ceil(glm::vec2(img.width, img.height) * scale), { 16, 16 }, glm::vec2(8192));
if (scale != 1.f)
{
img_tmp = img.resize(new_size.x, new_size.y);
px = (glm::u8vec4*)img_tmp.data();
}
int div = new_size.x - 1; // TODO: handle height also
int idx_size = (div * div * 6) + (div * (div + 1) * 4);
int vertices_size = (div + 1)*(div + 1);
auto idx = std::make_unique<GLuint[]>(idx_size);
auto vertices = std::make_unique<vertex_t[]>(vertices_size);
std::vector<GLuint> idx(idx_size);
std::vector<vertex_t> vertices(vertices_size);
std::vector<int> nor_count((size_t)vertices_size, 0);
count[0] = div * div * 6;
count[1] = div * (div + 1) * 4;
ioff[0] = (GLvoid*)0;
ioff[1] = (GLvoid*)(count[0] * sizeof(GLuint));
auto pv = vertices.get();
auto pi = idx.get();
auto px = (glm::u8vec4*)img.data();
auto pv = vertices.data();
auto pi = idx.data();
const float dx = w / div;
const float dy = h / div;
@@ -265,13 +278,99 @@ bool HeightmapPlane::create(float w, float h, const Image& img, float scale)
vertex_t v;
v.pos.x = ox + dx * (float)x;
v.pos.y = oy + dy * (float)y;
v.pos.z = (*px++).r / 255.f * scale;
v.pos.z = (*px++).r / 255.f;
v.pos.w = 1;
v.uvs2 = v.uvs = glm::vec2(x, y) / (float)div;
*pv++ = v;
}
}
// generate indices
for (int y = 0; y < div; y++)
{
int i = y * (div + 1);
for (int x = 0; x < div; x++)
{
*pi++ = i;
*pi++ = i + div + 1;
*pi++ = i + div + 2;
*pi++ = i;
*pi++ = i + div + 2;
*pi++ = i + 1;
auto n = glm::triangleNormal(xyz(vertices[i].pos),
xyz(vertices[i + div + 1].pos), xyz(vertices[i + 1].pos));
vertices[i].nor += n;
vertices[i + 1].nor += n;
vertices[i + div + 1].nor += n;
vertices[i + div + 2].nor += n;
nor_count[i]++;
nor_count[i + 1]++;
nor_count[i + div + 1]++;
nor_count[i + div + 2]++;
i++;
}
}
for (int i = 0; i < vertices_size; i++)
vertices[i].nor /= (float)nor_count[i];
// generate indices
for (int y = 0; y <= div; y++)
{
//int i = y * (div + 1);
for (int x = 0; x <= div; x++)
{
if (x < div)
{
*pi++ = y * (div + 1) + x;
*pi++ = y * (div + 1) + x + 1;
}
if (y < div)
{
*pi++ = y * (div + 1) + x;
*pi++ = (y + 1) * (div + 1) + x;
}
}
}
return create_buffers(idx.data(), vertices.data(), sizeof(GLuint) * idx_size, sizeof(vertex_t) * vertices_size);
}
bool HeightmapPlane::create(float w, float h, int div)
{
int idx_size = (div * div * 6) + (div * (div + 1) * 4);
int vertices_size = (div + 1)*(div + 1);
auto idx = std::make_unique<GLuint[]>(idx_size);
auto vertices = std::make_unique<vertex_t[]>(vertices_size);
count[0] = div * div * 6;
count[1] = div * (div + 1) * 4;
ioff[0] = (GLvoid*)0;
ioff[1] = (GLvoid*)(count[0] * sizeof(GLuint));
auto pv = vertices.get();
auto pi = idx.get();
const float dx = w / div;
const float dy = h / div;
const float ox = -w * 0.5f;
const float oy = -h * 0.5f;
for (int y = 0; y <= div; y++)
{
for (int x = 0; x <= div; x++)
{
vertex_t v;
v.pos.x = ox + dx * (float)x;
v.pos.y = oy + dy * (float)y;
v.pos.z = 0.f;
v.pos.w = 1.f;
v.uvs2 = v.uvs = glm::vec2(x, y) / (float)div;
v.nor = { 0, 1, 0 };
*pv++ = v;
}
}
// generate indices
for (int y = 0; y < div; y++)
{