implement grid and heightmap with lambert shading
This commit is contained in:
113
src/shape.cpp
113
src/shape.cpp
@@ -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++)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user