43 const std::vector<Atom> & atoms,
44 uint8_t levelOfDetail = 0,
45 glm::vec3 cameraPosition = glm::vec3(0),
47 float clipCorrection = 1.5f
50 meshShader = std::make_unique<jGL::GL::glShader>(meshVertexShader, meshFragmentShader);
51 imposterShader = std::make_unique<jGL::GL::glShader>(imposterVertexShader, imposterFragmentShader);
52 imposterShader->use();
53 imposterShader->setUniform<
float>(
"clipCorrection", clipCorrection);
54 imposterShader->setUniform<glm::vec4>(
"lightColour", glm::vec4(1.0f,1.0f,1.0f,1.0f));
55 imposterShader->setUniform<
float>(
"ambientLight", 0.1f);
58 meshShader->setUniform<glm::vec4>(
"lightColour", glm::vec4(1.0f,1.0f,1.0f,1.0f));
59 meshShader->setUniform<
float>(
"ambientLight", 0.1f);
63 std::vector<HierarchicalTriangularMesh<float>> htms;
75 for (uint8_t i = 0; i < 7; i++)
83 std::sort(htms.begin(), htms.end());
85 for (uint8_t i = 0; i < htms.size(); i++)
87 meshes.insert({i, {htms[i].vertices(), htms[i].vertexNormals()}});
88 triangleCounts.push_back(htms[i].
triangles());
93 for (uint8_t i = 0; i < 7; i++)
98 triangleCounts.push_back(htm.
triangles());
102 buffer = std::make_unique<AtomBuffer>
111 this->cameraPosition = cameraPosition;
112 cameraDistances.resize(atoms.size());
118 jGL::GL::glError(
"AtomRenderer::AtomRenderer");
136 triangles += buffer->atomCount()*triangleCounts[levelOfDetail];
146 void setLevelOfDetail(uint8_t lod){ levelOfDetail = std::min(lod, uint8_t(meshes.size()-1)); }
171 buffer->insert(atoms);
172 buffer->updateVertexArray();
180 void draw(
bool imposters =
true)
184 imposterShader->use();
190 buffer->draw(imposters);
191 jGL::GL::glError(
"AtomRenderer::draw");
199 void setView(glm::mat4 v) { view = v; setProjectionView(); }
218 glm::vec3 colour = {1.0f, 1.0f, 1.0f},
222 cameraPosition = position;
224 meshShader->setUniform<glm::vec4>(
"lightPos", glm::vec4(position, 1.0f));
225 meshShader->setUniform<glm::vec4>(
"lightColour", glm::vec4(colour, 1.0f));
226 meshShader->setUniform<
float>(
"ambientLight", ambient);
227 imposterShader->use();
228 imposterShader->setUniform<glm::vec4>(
"lightPos", glm::vec4(position, 1.0f));
229 imposterShader->setUniform<glm::vec4>(
"lightColour", glm::vec4(colour, 1.0f));
230 imposterShader->setUniform<
float>(
"ambientLight", ambient);
242 meshShader->setUniform<glm::vec4>(
"lightPos", glm::vec4(cameraPosition, 1.0f));
243 imposterShader->use();
244 imposterShader->setUniform<glm::vec4>(
"lightPos", glm::vec4(cameraPosition, 1.0f));
248 buffer->updateCamera(cameraPosition);
259 meshShader->setUniform<
float>(
"scaling", s);
260 imposterShader->use();
261 imposterShader->setUniform<
float>(
"scaling", s);
279 globalAlpha = std::max(0.0f, std::min(alpha, 1.0f));
281 meshShader->setUniform<
float>(
"globalAlpha", globalAlpha);
282 imposterShader->use();
283 imposterShader->setUniform<
float>(
"globalAlpha", globalAlpha);
288 std::unique_ptr<jGL::GL::glShader> meshShader, imposterShader;
289 glm::vec3 cameraPosition;
290 uint8_t levelOfDetail;
292 struct SphereMesh { std::vector<float> vertices; std::vector<float> normals; };
294 std::map<uint8_t, SphereMesh> meshes;
296 uint64_t atomCount = 0;
297 std::vector<uint32_t> triangleCounts;
299 std::vector<float> cameraDistances;
301 glm::mat4 view, projection;
303 float globalAlpha = 1.0f;
305 const char * meshVertexShader =
306 "#version " GLSL_VERSION
"\n"
307 "precision lowp float; precision lowp int;\n"
308 "layout(location=0) in vec3 a_vertices;\n"
309 "layout(location=1) in vec3 a_normals;\n"
310 "layout(location=2) in vec4 a_positionsAndScales;\n"
311 "layout(location=3) in vec4 a_colours;\n"
312 "uniform mat4 proj;\n"
313 "uniform float scaling;\n"
314 "out vec4 o_colour;\n"
315 "out vec3 o_normal;\n"
316 "out vec3 fragPos;\n"
320 " fragPos = vec3(a_vertices*a_positionsAndScales.w*scaling+a_positionsAndScales.xyz);\n"
321 " gl_Position = proj*vec4(fragPos.xyz, 1.0);\n"
322 " o_colour = a_colours;\n"
323 " o_normal = a_normals;\n"
326 const char * meshFragmentShader =
327 "#version " GLSL_VERSION
"\n"
328 "precision lowp float; precision lowp int;\n"
329 "uniform vec4 lightPos;\n"
330 "uniform vec4 lightColour;\n"
331 "uniform float ambientLight;\n"
332 "uniform float globalAlpha;\n"
333 "in vec4 o_colour;\n"
334 "in vec3 o_normal;\n"
339 " vec3 lightDir = normalize(lightPos.xyz - fragPos);\n"
340 " float diff = max(dot(normalize(o_normal), lightDir), 0.0);\n"
341 " colour = vec4((ambientLight + diff)*lightColour.rgb * o_colour.rgb, o_colour.a*globalAlpha);\n"
344 const char * imposterVertexShader =
345 "#version " GLSL_VERSION
"\n"
346 "precision lowp float; precision lowp int;\n"
347 "layout(location=0) in vec2 a_vertices;\n"
348 "layout(location=1) in vec4 a_positionsAndScales;\n"
349 "layout(location=2) in vec4 a_colours;\n"
350 "out vec2 billboard;\n"
351 "uniform mat4 view;\n"
352 "uniform mat4 proj;\n"
353 "uniform float clipCorrection;\n"
354 "uniform float scaling;\n"
355 "out vec4 atomPosScale;\n"
356 "out vec3 atomViewPos;\n"
357 "out vec4 o_colour;\n"
360 " billboard = a_vertices * clipCorrection;\n"
361 " atomViewPos = (view * vec4(a_positionsAndScales.xyz, 1.0)).xyz;"
362 " gl_Position = proj * (vec4(atomViewPos, 1.0)+vec4(scaling*a_positionsAndScales.w * a_vertices * clipCorrection, 0.0, 1.0));"
363 " atomPosScale = a_positionsAndScales;\n"
364 " atomPosScale.w *= scaling;\n"
365 " o_colour = a_colours;\n"
368 const char * imposterFragmentShader =
369 "#version " GLSL_VERSION
"\n"
370 "precision lowp float; precision lowp int;\n"
371 "in vec2 billboard;\n"
372 "in vec3 atomViewPos;\n"
373 "in vec4 atomPosScale;\n"
374 "in vec4 o_colour;\n"
376 "uniform mat4 view;\n"
377 "uniform mat4 proj;\n"
378 "uniform vec4 lightPos;\n"
379 "uniform vec4 lightColour;\n"
380 "uniform float ambientLight;\n"
381 "uniform float globalAlpha;\n"
382 "bool sphereHit(vec3 rayDirection, vec3 centre, float radius, out vec3 pos, out vec3 normal)\n"
384 " float b = 2.0 * dot(rayDirection, -centre);\n"
385 " float r2 = radius*radius;\n"
386 " float determinant = b * b - (4.0 * (dot(centre, centre) - r2));\n"
387 " if(determinant < 0.0) { return false; }\n"
388 " determinant = sqrt(determinant);\n"
389 " pos = rayDirection * min((-b+determinant)*0.5, (-b-determinant)*0.5);\n"
390 " normal = normalize(pos - centre);\n"
395 " if (o_colour.a == 0.0) { discard; }\n"
396 " vec3 lightViewPos = (view*lightPos).xyz;\n"
397 " vec3 rayDirection = normalize(vec3(billboard * atomPosScale.w, 0.0) + atomViewPos);"
398 " vec3 viewNormal; vec3 viewPos;\n"
399 " bool hit = sphereHit(rayDirection, atomViewPos, atomPosScale.w, viewPos, viewNormal);\n"
400 " if (!hit) { discard; }\n"
401 " vec4 clipPos = proj * vec4(viewPos, 1.0);\n"
402 " float ndcDepth = clipPos.z / clipPos.w;\n"
403 " gl_FragDepth = ((gl_DepthRange.diff * ndcDepth) + gl_DepthRange.near + gl_DepthRange.far) / 2.0;\n"
404 " float diff = max(dot(normalize(viewNormal), normalize(lightViewPos-atomViewPos)), 0.0);\n"
405 " colour = vec4((ambientLight + diff)*lightColour.rgb * o_colour.rgb, o_colour.a*globalAlpha);\n"
408 void setProjectionView()
410 meshShader->setUniform<glm::mat4>(
"proj", projection*view);
411 imposterShader->setUniform<glm::mat4>(
"view", view);
412 imposterShader->setUniform<glm::mat4>(
"proj", projection);
430 std::map<uint8_t, SphereMesh> meshes,
432 uint8_t levelOfDetail,
433 glm::vec3 cameraPosition
437 levelOfDetail(std::
min(meshes.size()-1, size_t(levelOfDetail))),
438 cameraPosition(cameraPosition)
440 glGenVertexArrays(1, &vao_mesh);
441 glGenVertexArrays(1, &vao_imposter);
442 glGenBuffers(1, &a_quad);
443 glGenBuffers(1, &a_colours);
444 glGenBuffers(1, &a_positionsAndScales);
446 a_meshVertices = std::vector<GLuint>(meshes.size(), 0);
447 a_meshNormals = std::vector<GLuint>(meshes.size(), 0);
448 glGenBuffers(a_meshVertices.size(), a_meshVertices.data());
449 glGenBuffers(a_meshNormals.size(), a_meshNormals.data());
451 positionsAndScales.resize(size*4);
452 colours.resize(size*4);
454 glBindVertexArray(vao_mesh);
458 a_meshVertices[this->levelOfDetail],
459 meshes[this->levelOfDetail].vertices.data(),
460 meshes[this->levelOfDetail].vertices.size(),
469 a_meshNormals[this->levelOfDetail],
470 meshes[this->levelOfDetail].normals.data(),
471 meshes[this->levelOfDetail].normals.size(),
480 a_positionsAndScales,
481 positionsAndScales.data(),
482 positionsAndScales.size(),
500 glBindVertexArray(0);
502 glBindVertexArray(vao_imposter);
517 a_positionsAndScales,
531 glBindVertexArray(0);
536 glDeleteBuffers(a_meshVertices.size(), a_meshVertices.data());
537 glDeleteBuffers(a_meshNormals.size(), a_meshNormals.data());
538 glDeleteBuffers(1, &a_colours);
539 glDeleteBuffers(1, &a_positionsAndScales);
540 glDeleteBuffers(1, &a_quad);
541 glDeleteVertexArrays(1, &vao_mesh);
542 glDeleteVertexArrays(1, &vao_imposter);
549 void flip() { index = 0; atoms = 0; }
556 void insert(
const Atom & atom)
558 if (atom.
colour.a == 0.0) {
return; }
559 positionsAndScales[index] = atom.
position.x;
560 positionsAndScales[index+1] = atom.
position.y;
561 positionsAndScales[index+2] = atom.
position.z;
562 positionsAndScales[index+3] = atom.
scale;
564 colours[index] = atom.
colour.r;
565 colours[index+1] = atom.
colour.g;
566 colours[index+2] = atom.
colour.b;
567 colours[index+3] = atom.
colour.a;
577 uint32_t atomCount()
const {
return atoms; }
585 void draw(uint32_t count,
bool imposters)
587 count = std::min(count, atoms);
588 if (count == 0) {
return; }
591 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
592 glEnable(GL_DEPTH_TEST);
593 glEnable(GL_CULL_FACE);
598 glBindVertexArray(vao_imposter);
600 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
602 glBindVertexArray(0);
607 glBindVertexArray(vao_mesh);
609 glDrawArraysInstanced(GL_TRIANGLES, 0, meshes[levelOfDetail].vertices.size(), count);
611 glBindVertexArray(0);
620 void setLevelOfDetail(uint8_t levelOfDetail)
623 this->levelOfDetail = std::min(
size_t(levelOfDetail), meshes.size()-1);
624 glBindVertexArray(vao_mesh);
627 a_meshVertices[this->levelOfDetail],
628 meshes[this->levelOfDetail].vertices.data(),
629 meshes[this->levelOfDetail].vertices.size(),
638 a_meshNormals[this->levelOfDetail],
639 meshes[this->levelOfDetail].normals.data(),
640 meshes[this->levelOfDetail].normals.size(),
646 glBindVertexArray(0);
654 void draw(
bool imposters =
true) { draw(atoms, imposters); }
661 void insert(
const std::vector<Atom> & atoms)
664 for (
const Atom & atom : atoms) { insert(atom); }
671 void updateVertexArray()
674 glBindVertexArray(vao_mesh);
676 subFullBuffer(a_positionsAndScales, positionsAndScales.data(), positionsAndScales.size());
679 glBindVertexArray(0);
688 void updateCamera(glm::vec3 position)
690 cameraPosition = position;
691 if (transparencySortingEnabled) { updateVertexArray(); };
701 transparencySortingEnabled = sort;
702 if (transparencySortingEnabled) { updateVertexArray(); };
707 std::map<uint8_t, SphereMesh> meshes;
709 uint8_t levelOfDetail;
710 glm::vec3 cameraPosition;
711 GLuint vao_mesh, vao_imposter, a_quad, a_positionsAndScales, a_colours;
712 std::vector<GLuint> a_meshVertices, a_meshNormals;
714 std::vector<float> positionsAndScales;
715 std::vector<float> colours;
719 bool transparencySortingEnabled =
true;
721 const std::array<float, 8> quad =
732 if (!transparencySortingEnabled || atoms == 0) {
return; }
736 std::vector<std::pair<float, uint64_t>> order;
737 order.reserve(atoms);
738 for (uint64_t i = 0; i < atoms; i++)
740 float rx = positionsAndScales[i*4]-cameraPosition.x;
741 float ry = positionsAndScales[i*4+1]-cameraPosition.y;
742 float rz = positionsAndScales[i*4+2]-cameraPosition.z;
743 float d2 = rx*rx+ry*ry+rz*rz+positionsAndScales[i*4+3]*positionsAndScales[i*4+3];
744 order.push_back({d2, i});
752 const std::pair<float, uint64_t> & a,
753 const std::pair<float, uint64_t> & b
756 return a.first > b.first;
761 std::vector<float> positionsAndScales_tmp = positionsAndScales;
762 std::vector<float> colours_tmp = colours;
763 for (
auto iter = order.begin(); iter != order.end(); iter++)
765 positionsAndScales[index] = positionsAndScales_tmp[iter->second*4];
766 positionsAndScales[index+1] = positionsAndScales_tmp[iter->second*4+1];
767 positionsAndScales[index+2] = positionsAndScales_tmp[iter->second*4+2];
768 positionsAndScales[index+3] = positionsAndScales_tmp[iter->second*4+3];
770 colours[index] = colours_tmp[iter->second*4];
771 colours[index+1] = colours_tmp[iter->second*4+1];
772 colours[index+2] = colours_tmp[iter->second*4+2];
773 colours[index+3] = colours_tmp[iter->second*4+3];
779 std::unique_ptr<AtomBuffer> buffer;
void setTransparencySorting(const std::vector< Atom > &atoms, AtomRenderer &atomRenderer, BondRenderer &bondRenderer)
Enable of disable transparency sorting if there are transparent elements.
Definition main.h:342