Skip to content

Commit

Permalink
Use singleton shaders (OpenChemistry#1156)
Browse files Browse the repository at this point in the history
* Declare cylinder, sphere, mesh, and text shaders static

Ensures they're only initialized once.
Definitely seems to improve interaction speed.

Signed-off-by: Geoff Hutchison <[email protected]>
  • Loading branch information
ghutchis authored Aug 29, 2022
1 parent 2d1dbda commit 10edf92
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 151 deletions.
95 changes: 51 additions & 44 deletions avogadro/rendering/cylindergeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class CylinderGeometry::Private
BufferObject vbo;
BufferObject ibo;

Shader vertexShader;
Shader fragmentShader;
ShaderProgram program;
inline static Shader* vertexShader = nullptr;
inline static Shader* fragmentShader = nullptr;
inline static ShaderProgram* program = nullptr;

size_t numberOfVertices;
size_t numberOfIndices;
Expand Down Expand Up @@ -76,7 +76,7 @@ void CylinderGeometry::update()
// Check if the VBOs are ready, if not get them ready.
if (!d->vbo.ready() || m_dirty) {
// Set some defaults for our cylinders.
const unsigned int resolution = 12; // points per circle
const unsigned int resolution = 8; // points per circle
const float resolutionRadians =
2.0f * static_cast<float>(M_PI) / static_cast<float>(resolution);
std::vector<Vector3f> radials;
Expand Down Expand Up @@ -144,24 +144,31 @@ void CylinderGeometry::update()
}

// Build and link the shader if it has not been used yet.
if (d->vertexShader.type() == Shader::Unknown) {
d->vertexShader.setType(Shader::Vertex);
d->vertexShader.setSource(cylinders_vs);
d->fragmentShader.setType(Shader::Fragment);
d->fragmentShader.setSource(cylinders_fs);
if (!d->vertexShader.compile())
cout << d->vertexShader.error() << endl;
if (!d->fragmentShader.compile())
cout << d->fragmentShader.error() << endl;
d->program.attachShader(d->vertexShader);
d->program.attachShader(d->fragmentShader);
if (!d->program.link())
cout << d->program.error() << endl;

d->program.detachShader(d->vertexShader);
d->program.detachShader(d->fragmentShader);
if (d->vertexShader == nullptr) {
d->vertexShader = new Shader;
d->vertexShader->setType(Shader::Vertex);
d->vertexShader->setSource(cylinders_vs);
d->fragmentShader = new Shader;
d->fragmentShader->setType(Shader::Fragment);
d->fragmentShader->setSource(cylinders_fs);
if (!d->vertexShader->compile())
cout << d->vertexShader->error() << endl;
if (!d->fragmentShader->compile())
cout << d->fragmentShader->error() << endl;

if (d->program == nullptr)
d->program = new ShaderProgram;

d->program->attachShader(*d->vertexShader);
d->program->attachShader(*d->fragmentShader);
if (!d->program->link())
cout << d->program->error() << endl;

/* d->program->detachShader(d->vertexShader);
d->program->detachShader(d->fragmentShader);
d->vertexShader.cleanup();
d->fragmentShader.cleanup();
*/
}
}

Expand All @@ -173,45 +180,45 @@ void CylinderGeometry::render(const Camera& camera)
// Prepare the VBOs, IBOs and shader program if necessary.
update();

if (!d->program.bind())
cout << d->program.error() << endl;
if (!d->program->bind())
cout << d->program->error() << endl;

d->vbo.bind();
d->ibo.bind();

// Set up our attribute arrays.
if (!d->program.enableAttributeArray("vertex"))
cout << d->program.error() << endl;
if (!d->program.useAttributeArray("vertex", ColorNormalVertex::vertexOffset(),
if (!d->program->enableAttributeArray("vertex"))
cout << d->program->error() << endl;
if (!d->program->useAttributeArray("vertex", ColorNormalVertex::vertexOffset(),
sizeof(ColorNormalVertex), FloatType, 3,
ShaderProgram::NoNormalize)) {
cout << d->program.error() << endl;
cout << d->program->error() << endl;
}
if (!d->program.enableAttributeArray("color"))
cout << d->program.error() << endl;
if (!d->program.useAttributeArray("color", ColorNormalVertex::colorOffset(),
if (!d->program->enableAttributeArray("color"))
cout << d->program->error() << endl;
if (!d->program->useAttributeArray("color", ColorNormalVertex::colorOffset(),
sizeof(ColorNormalVertex), UCharType, 3,
ShaderProgram::Normalize)) {
cout << d->program.error() << endl;
cout << d->program->error() << endl;
}
if (!d->program.enableAttributeArray("normal"))
cout << d->program.error() << endl;
if (!d->program.useAttributeArray("normal", ColorNormalVertex::normalOffset(),
if (!d->program->enableAttributeArray("normal"))
cout << d->program->error() << endl;
if (!d->program->useAttributeArray("normal", ColorNormalVertex::normalOffset(),
sizeof(ColorNormalVertex), FloatType, 3,
ShaderProgram::NoNormalize)) {
cout << d->program.error() << endl;
cout << d->program->error() << endl;
}

// Set up our uniforms (model-view and projection matrices right now).
if (!d->program.setUniformValue("modelView", camera.modelView().matrix())) {
cout << d->program.error() << endl;
if (!d->program->setUniformValue("modelView", camera.modelView().matrix())) {
cout << d->program->error() << endl;
}
if (!d->program.setUniformValue("projection", camera.projection().matrix())) {
cout << d->program.error() << endl;
if (!d->program->setUniformValue("projection", camera.projection().matrix())) {
cout << d->program->error() << endl;
}
Matrix3f normalMatrix = camera.modelView().linear().inverse().transpose();
if (!d->program.setUniformValue("normalMatrix", normalMatrix))
std::cout << d->program.error() << std::endl;
if (!d->program->setUniformValue("normalMatrix", normalMatrix))
std::cout << d->program->error() << std::endl;

// Render the loaded spheres using the shader and bound VBO.
glDrawRangeElements(GL_TRIANGLES, 0, static_cast<GLuint>(d->numberOfVertices),
Expand All @@ -221,11 +228,11 @@ void CylinderGeometry::render(const Camera& camera)
d->vbo.release();
d->ibo.release();

d->program.disableAttributeArray("vector");
d->program.disableAttributeArray("color");
d->program.disableAttributeArray("normal");
d->program->disableAttributeArray("vector");
d->program->disableAttributeArray("color");
d->program->disableAttributeArray("normal");

d->program.release();
d->program->release();
}

std::multimap<float, Identifier> CylinderGeometry::hits(
Expand Down
71 changes: 40 additions & 31 deletions avogadro/rendering/meshgeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ class MeshGeometry::Private
BufferObject vbo;
BufferObject ibo;

Shader vertexShader;
Shader fragmentShader;
Shader fragmentShaderOpaque;
ShaderProgram program;
ShaderProgram programOpaque;
inline static Shader* vertexShader = nullptr;
inline static Shader* fragmentShader = nullptr;
inline static Shader* fragmentShaderOpaque = nullptr;
inline static ShaderProgram* program = nullptr;
inline static ShaderProgram* programOpaque = nullptr;

size_t numberOfVertices;
size_t numberOfIndices;
Expand Down Expand Up @@ -92,30 +92,39 @@ void MeshGeometry::update()
}

// Build and link the shader if it has not been used yet.
if (d->vertexShader.type() == Shader::Unknown) {
d->vertexShader.setType(Shader::Vertex);
d->vertexShader.setSource(mesh_vs);
d->fragmentShader.setType(Shader::Fragment);
d->fragmentShader.setSource(mesh_fs);
d->fragmentShaderOpaque.setType(Shader::Fragment);
d->fragmentShaderOpaque.setSource(mesh_opaque_fs);

if (!d->vertexShader.compile())
cout << d->vertexShader.error() << endl;
if (!d->fragmentShader.compile())
cout << d->fragmentShader.error() << endl;
if (!d->fragmentShaderOpaque.compile())
cout << d->fragmentShaderOpaque.error() << endl;

d->program.attachShader(d->vertexShader);
d->program.attachShader(d->fragmentShader);
if (!d->program.link())
cout << d->program.error() << endl;

d->programOpaque.attachShader(d->vertexShader);
d->programOpaque.attachShader(d->fragmentShaderOpaque);
if (!d->programOpaque.link())
cout << d->programOpaque.error() << endl;
if (d->vertexShader == nullptr) {
d->vertexShader = new Shader;
d->vertexShader->setType(Shader::Vertex);
d->vertexShader->setSource(mesh_vs);

d->fragmentShader = new Shader;
d->fragmentShader->setType(Shader::Fragment);
d->fragmentShader->setSource(mesh_fs);

d->fragmentShaderOpaque = new Shader;
d->fragmentShaderOpaque->setType(Shader::Fragment);
d->fragmentShaderOpaque->setSource(mesh_opaque_fs);

if (!d->vertexShader->compile())
cout << d->vertexShader->error() << endl;
if (!d->fragmentShader->compile())
cout << d->fragmentShader->error() << endl;
if (!d->fragmentShaderOpaque->compile())
cout << d->fragmentShaderOpaque->error() << endl;

if (d->program == nullptr)
d->program = new ShaderProgram;
d->program->attachShader(*d->vertexShader);
d->program->attachShader(*d->fragmentShader);
if (!d->program->link())
cout << d->program->error() << endl;

if (d->programOpaque == nullptr)
d->programOpaque = new ShaderProgram;
d->programOpaque->attachShader(*d->vertexShader);
d->programOpaque->attachShader(*d->fragmentShaderOpaque);
if (!d->programOpaque->link())
cout << d->programOpaque->error() << endl;
}
}

Expand All @@ -130,9 +139,9 @@ void MeshGeometry::render(const Camera& camera)
ShaderProgram* program;
// If the mesh is opaque, use the opaque shader
if (m_opacity != 255)
program = &d->program;
program = d->program;
else
program = &d->programOpaque;
program = d->programOpaque;

if (!program->bind())
cout << program->error() << endl;
Expand Down
90 changes: 49 additions & 41 deletions avogadro/rendering/spheregeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ class SphereGeometry::Private
BufferObject vbo;
BufferObject ibo;

Shader vertexShader;
Shader fragmentShader;
ShaderProgram program;
inline static Shader* vertexShader = nullptr;
inline static Shader* fragmentShader = nullptr;
inline static ShaderProgram* program = nullptr;

size_t numberOfVertices;
size_t numberOfIndices;
Expand Down Expand Up @@ -123,24 +123,32 @@ void SphereGeometry::update()
}

// Build and link the shader if it has not been used yet.
if (d->vertexShader.type() == Shader::Unknown) {
d->vertexShader.setType(Shader::Vertex);
d->vertexShader.setSource(spheres_vs);
d->fragmentShader.setType(Shader::Fragment);
d->fragmentShader.setSource(spheres_fs);
if (!d->vertexShader.compile())
cout << d->vertexShader.error() << endl;
if (!d->fragmentShader.compile())
cout << d->fragmentShader.error() << endl;
d->program.attachShader(d->vertexShader);
d->program.attachShader(d->fragmentShader);
if (!d->program.link())
cout << d->program.error() << endl;

if (d->vertexShader == nullptr) {
d->vertexShader = new Shader;
d->vertexShader->setType(Shader::Vertex);
d->vertexShader->setSource(spheres_vs);
d->fragmentShader = new Shader;
d->fragmentShader->setType(Shader::Fragment);
d->fragmentShader->setSource(spheres_fs);
if (!d->vertexShader->compile())
cout << d->vertexShader->error() << endl;
if (!d->fragmentShader->compile())
cout << d->fragmentShader->error() << endl;

if (d->program == nullptr)
d->program = new ShaderProgram;

d->program->attachShader(*d->vertexShader);
d->program->attachShader(*d->fragmentShader);
if (!d->program->link())
cout << d->program->error() << endl;

/*
d->program.detachShader(d->vertexShader);
d->program.detachShader(d->fragmentShader);
d->vertexShader.cleanup();
d->fragmentShader.cleanup();
*/
}
}

Expand All @@ -152,44 +160,44 @@ void SphereGeometry::render(const Camera& camera)
// Prepare the VBOs, IBOs and shader program if necessary.
update();

if (!d->program.bind())
cout << d->program.error() << endl;
if (!d->program->bind())
cout << d->program->error() << endl;

d->vbo.bind();
d->ibo.bind();

// Set up our attribute arrays.
if (!d->program.enableAttributeArray("vertex"))
cout << d->program.error() << endl;
if (!d->program.useAttributeArray(
if (!d->program->enableAttributeArray("vertex"))
cout << d->program->error() << endl;
if (!d->program->useAttributeArray(
"vertex", ColorTextureVertex::vertexOffset(),
sizeof(ColorTextureVertex), FloatType, 3, ShaderProgram::NoNormalize)) {
cout << d->program.error() << endl;
cout << d->program->error() << endl;
}
if (!d->program.enableAttributeArray("color"))
cout << d->program.error() << endl;
if (!d->program.useAttributeArray("color", ColorTextureVertex::colorOffset(),
if (!d->program->enableAttributeArray("color"))
cout << d->program->error() << endl;
if (!d->program->useAttributeArray("color", ColorTextureVertex::colorOffset(),
sizeof(ColorTextureVertex), UCharType, 3,
ShaderProgram::Normalize)) {
cout << d->program.error() << endl;
cout << d->program->error() << endl;
}
if (!d->program.enableAttributeArray("texCoordinate"))
cout << d->program.error() << endl;
if (!d->program.useAttributeArray(
if (!d->program->enableAttributeArray("texCoordinate"))
cout << d->program->error() << endl;
if (!d->program->useAttributeArray(
"texCoordinate", ColorTextureVertex::textureCoordOffset(),
sizeof(ColorTextureVertex), FloatType, 2, ShaderProgram::NoNormalize)) {
cout << d->program.error() << endl;
cout << d->program->error() << endl;
}

// Set up our uniforms (model-view and projection matrices right now).
if (!d->program.setUniformValue("modelView", camera.modelView().matrix())) {
cout << d->program.error() << endl;
if (!d->program->setUniformValue("modelView", camera.modelView().matrix())) {
cout << d->program->error() << endl;
}
if (!d->program.setUniformValue("projection", camera.projection().matrix())) {
cout << d->program.error() << endl;
if (!d->program->setUniformValue("projection", camera.projection().matrix())) {
cout << d->program->error() << endl;
}
if (!d->program.setUniformValue("opacity", m_opacity)) {
cout << d->program.error() << endl;
if (!d->program->setUniformValue("opacity", m_opacity)) {
cout << d->program->error() << endl;
}

// Render the loaded spheres using the shader and bound VBO.
Expand All @@ -200,11 +208,11 @@ void SphereGeometry::render(const Camera& camera)
d->vbo.release();
d->ibo.release();

d->program.disableAttributeArray("vector");
d->program.disableAttributeArray("color");
d->program.disableAttributeArray("texCoordinates");
d->program->disableAttributeArray("vector");
d->program->disableAttributeArray("color");
d->program->disableAttributeArray("texCoordinates");

d->program.release();
d->program->release();
}

std::multimap<float, Identifier> SphereGeometry::hits(
Expand Down
Loading

0 comments on commit 10edf92

Please sign in to comment.