diff --git a/avogadro/rendering/CMakeLists.txt b/avogadro/rendering/CMakeLists.txt index ddebfe8483..e965584da7 100644 --- a/avogadro/rendering/CMakeLists.txt +++ b/avogadro/rendering/CMakeLists.txt @@ -106,6 +106,8 @@ set(shader_files "mesh_fs.glsl" "mesh_opaque_fs.glsl" "mesh_vs.glsl" + "mesh_tcs.glsl" + "mesh_tev.glsl" "solid_vs.glsl" "solid_first_fs.glsl" "spheres_fs.glsl" diff --git a/avogadro/rendering/mesh_fs.glsl b/avogadro/rendering/mesh_fs.glsl index 00f47e54d1..d01cd8f1ee 100644 --- a/avogadro/rendering/mesh_fs.glsl +++ b/avogadro/rendering/mesh_fs.glsl @@ -1,17 +1,23 @@ -varying vec3 fnormal; +#version 400 +precision highp float; + +in vec3 teNormal; +in vec4 teColor; + +out vec4 colorOut; void main() { - vec3 N = normalize(fnormal); - vec3 L = normalize(vec3(0, 1, 1)); - vec3 E = vec3(0, 0, 1); - vec3 H = normalize(L + E); - float df = max(0.0, dot(N, L)); - float sf = max(0.0, dot(N, H)); - sf = pow(sf, 20.0); - vec4 ambient = gl_Color / 3.0; - vec4 diffuse = gl_Color; - vec4 specular = gl_Color * 3.0; - gl_FragColor = ambient + df * diffuse + sf * specular; - gl_FragColor.a = gl_Color.a; + vec3 N = normalize(teNormal); + vec3 L = normalize(vec3(0, 1, 1)); + vec3 E = vec3(0, 0, 1); + vec3 H = normalize(L + E); + float df = max(0.0, dot(N, L)); + float sf = max(0.0, dot(N, H)); + sf = pow(sf, 20.0); + vec4 ambient = teColor / 3.0; + vec4 diffuse = teColor; + vec4 specular = teColor * 3.0; + colorOut = ambient + df * diffuse + sf * specular; + colorOut.a = teColor.a; } diff --git a/avogadro/rendering/mesh_opaque_fs.glsl b/avogadro/rendering/mesh_opaque_fs.glsl index d3a5bb4f85..d4e83a6e60 100644 --- a/avogadro/rendering/mesh_opaque_fs.glsl +++ b/avogadro/rendering/mesh_opaque_fs.glsl @@ -1,17 +1,24 @@ -varying vec3 fnormal; +#version 400 +precision highp float; + +in vec3 teNormal; +in vec4 teColor; + +out vec4 colorOut; + void main() { - vec3 N = normalize(fnormal); - vec3 L = normalize(vec3(0, 1, 1)); - vec3 E = vec3(0, 0, 1); - vec3 H = normalize(L + E); - float df = max(0.0, dot(N, -L)); - float sf = max(0.0, dot(N, -H)); - sf = pow(sf, 32.0); - vec4 ambient = gl_Color / 2.2; - vec4 diffuse = gl_Color * 1.1; - vec4 specular = gl_Color * 5.0; - gl_FragColor = ambient + df * diffuse + sf * specular; - gl_FragColor.a = gl_Color.a; + vec3 N = normalize(teNormal); + vec3 L = normalize(vec3(0.0, 1.0, 1.0)); + vec3 E = vec3(0.0, 0.0, 1.0); + vec3 H = normalize(L + E); + float df = max(0.0, dot(N, -L)); + float sf = max(0.0, dot(N, -H)); + sf = pow(sf, 20.0); + vec4 ambient = teColor / 2.2; + vec4 diffuse = teColor * 1.1; + vec4 specular = teColor * 5.0; + colorOut = ambient + df * diffuse + sf * specular; + colorOut.a = teColor.a; } diff --git a/avogadro/rendering/mesh_tcs.glsl b/avogadro/rendering/mesh_tcs.glsl new file mode 100644 index 0000000000..89ae073cc8 --- /dev/null +++ b/avogadro/rendering/mesh_tcs.glsl @@ -0,0 +1,83 @@ +#version 400 +precision highp float; + +layout(vertices = 1) out; + +in vec3 vsNormal[]; +in vec3 WorldPos_CS_in[]; +in vec2 TexCoord_CS_in[]; +in vec3 teVertex[]; +in vec4 vsColor[]; + +patch out vec3 WorldPos_B030; +patch out vec3 WorldPos_B012; +patch out vec3 WorldPos_B021; +patch out vec3 WorldPos_B003; +patch out vec3 WorldPos_B102; +patch out vec3 WorldPos_B201; +patch out vec3 WorldPos_B300; +patch out vec3 WorldPos_B210; +patch out vec3 WorldPos_B120; +patch out vec3 WorldPos_B111; + +patch out vec2 tcsVertex[3]; +patch out vec3 tcsNormal[3]; +patch out vec3 tevVertex[3]; +patch out vec4 tcsColor[3]; + +vec3 ProjectToPlane(vec3 Point, vec3 PlanePoint, vec3 PlaneNormal) +{ + vec3 v = Point - PlanePoint; + float Len = dot(v, PlaneNormal); + vec3 d = Len * PlaneNormal; + return (Point - d); +} + +void CalcPositions() +{ + WorldPos_B030 = WorldPos_CS_in[0]; + WorldPos_B003 = WorldPos_CS_in[1]; + WorldPos_B300 = WorldPos_CS_in[2]; + + vec3 EdgeB300 = WorldPos_B003 - WorldPos_B030; + vec3 EdgeB030 = WorldPos_B300 - WorldPos_B003; + vec3 EdgeB003 = WorldPos_B030 - WorldPos_B300; + + WorldPos_B021 = WorldPos_B030 + EdgeB300 / 3.0; + WorldPos_B012 = WorldPos_B030 + EdgeB300 * 2.0 / 3.0; + WorldPos_B102 = WorldPos_B003 + EdgeB030 / 3.0; + WorldPos_B201 = WorldPos_B003 + EdgeB030 * 2.0 / 3.0; + WorldPos_B210 = WorldPos_B300 + EdgeB003 / 3.0; + WorldPos_B120 = WorldPos_B300 + EdgeB003 * 2.0 / 3.0; + + WorldPos_B021 = ProjectToPlane(WorldPos_B021, WorldPos_B030, normalize(vsNormal[0])); + WorldPos_B012 = ProjectToPlane(WorldPos_B012, WorldPos_B003, normalize(vsNormal[1])); + WorldPos_B102 = ProjectToPlane(WorldPos_B102, WorldPos_B003, normalize(vsNormal[1])); + WorldPos_B201 = ProjectToPlane(WorldPos_B201, WorldPos_B300, normalize(vsNormal[2])); + WorldPos_B210 = ProjectToPlane(WorldPos_B210, WorldPos_B300, normalize(vsNormal[2])); + WorldPos_B120 = ProjectToPlane(WorldPos_B120, WorldPos_B030, normalize(vsNormal[0])); + + vec3 Center = (WorldPos_B003 + WorldPos_B030 + WorldPos_B300) / 3.0; + WorldPos_B111 = (WorldPos_B021 + WorldPos_B012 + WorldPos_B102 + + WorldPos_B201 + WorldPos_B210 + WorldPos_B120) / 6.0; + WorldPos_B111 += (WorldPos_B111 - Center) / 2.0; +} + +void main() +{ + for (int i = 0 ; i < 3 ; i++) { + tcsVertex[i] = TexCoord_CS_in[i]; + tevVertex[i] = teVertex[i]; + tcsNormal[i] = vsNormal[i]; + tcsColor[i] = vsColor[i]; + } + + CalcPositions(); + + gl_TessLevelOuter[0] = 50; + gl_TessLevelOuter[1] = 50; + gl_TessLevelOuter[2] = 50; + gl_TessLevelOuter[3] = 50; + gl_TessLevelInner[0] = 50; + gl_TessLevelInner[1] = 50; +} diff --git a/avogadro/rendering/mesh_tev.glsl b/avogadro/rendering/mesh_tev.glsl new file mode 100644 index 0000000000..3b31241cef --- /dev/null +++ b/avogadro/rendering/mesh_tev.glsl @@ -0,0 +1,76 @@ +#version 400 +precision highp float; + +layout(triangles, equal_spacing, ccw) in; + +patch in vec3 WorldPos_B030; +patch in vec3 WorldPos_B021; +patch in vec3 WorldPos_B012; +patch in vec3 WorldPos_B003; +patch in vec3 WorldPos_B102; +patch in vec3 WorldPos_B201; +patch in vec3 WorldPos_B300; +patch in vec3 WorldPos_B210; +patch in vec3 WorldPos_B120; +patch in vec3 WorldPos_B111; + +patch in vec2 tcsVertex[3]; +patch in vec3 tcsNormal[3]; +patch in vec3 tevVertex[3]; +patch in vec4 tcsColor[3]; + +out vec2 teVertex; +out vec3 teNormal; +out vec3 WorldPos_FS_in; +out vec4 teColor; + +uniform mat4 modelView; +uniform mat4 projection; + +vec3 interpolate3D(vec3 v0, vec3 v1, vec3 v2) +{ + return gl_TessCoord.x * v0 + gl_TessCoord.y * v1 + gl_TessCoord.z * v2; +} + +vec2 interpolate2D(vec2 v0, vec2 v1, vec2 v2) +{ + return gl_TessCoord.x * v0 + gl_TessCoord.y * v1 + gl_TessCoord.z * v2; +} + +vec4 interpolate4D(vec4 v0, vec4 v1, vec4 v2) +{ + return gl_TessCoord.x * v0 + gl_TessCoord.y * v1 + gl_TessCoord.z * v2; +} + +void main() +{ + vec2 p0 = tcsVertex[0]; + vec2 p1 = tcsVertex[1]; + vec2 p2 = tcsVertex[2]; + + vec3 n0 = tcsNormal[0]; + vec3 n1 = tcsNormal[1]; + vec3 n2 = tcsNormal[2]; + + teVertex = interpolate2D(p0, p1, p2); + teNormal = normalize(interpolate3D(tcsNormal[0], tcsNormal[1], tcsNormal[2])); + teColor = interpolate4D(tcsColor[0], tcsColor[1], tcsColor[2]); + + float u = gl_TessCoord.x; + float v = gl_TessCoord.y; + float w = gl_TessCoord.z; + + float uPow3 = pow(u, 3); + float vPow3 = pow(v, 3); + float wPow3 = pow(w, 3); + float uPow2 = pow(u, 2); + float vPow2 = pow(v, 2); + float wPow2 = pow(w, 2); + + WorldPos_FS_in = WorldPos_B300 * wPow3 + WorldPos_B030 * uPow3 + WorldPos_B003 * vPow3 + + WorldPos_B210 * 3.0 * wPow2 * u + WorldPos_B120 * 3.0 * w * uPow2 + WorldPos_B201 * 3.0 * wPow2 * v + + WorldPos_B021 * 3.0 * uPow2 * v + WorldPos_B102 * 3.0 * w * vPow2 + WorldPos_B012 * 3.0 * u * vPow2 + + WorldPos_B111 * 6.0 * w * u * v; + + gl_Position = projection * vec4(WorldPos_FS_in, 1.0); +} diff --git a/avogadro/rendering/mesh_vs.glsl b/avogadro/rendering/mesh_vs.glsl index c8cdcbfecb..81d0065ccf 100644 --- a/avogadro/rendering/mesh_vs.glsl +++ b/avogadro/rendering/mesh_vs.glsl @@ -1,16 +1,25 @@ -attribute vec4 vertex; -attribute vec4 color; -attribute vec3 normal; +#version 400 +precision highp float; + +in vec3 vertex; +in vec3 normal; +in vec4 color; uniform mat4 modelView; uniform mat4 projection; uniform mat3 normalMatrix; -varying vec3 fnormal; +out vec3 WorldPos_CS_in; +out vec2 TexCoord_CS_in; +out vec3 vsNormal; +out vec3 teVertex; +out vec4 vsColor; void main() { - gl_FrontColor = color; - gl_Position = projection * modelView * vertex; - fnormal = normalize(normalMatrix * normal); + vsColor = color; + teVertex = vertex; + WorldPos_CS_in = (modelView * vec4(vertex, 1.0)).xyz; + TexCoord_CS_in = vertex.xy; + vsNormal = normalize(normalMatrix * normal); } diff --git a/avogadro/rendering/meshgeometry.cpp b/avogadro/rendering/meshgeometry.cpp index d3736838cc..d87fecdf62 100644 --- a/avogadro/rendering/meshgeometry.cpp +++ b/avogadro/rendering/meshgeometry.cpp @@ -24,6 +24,8 @@ namespace { #include "mesh_fs.h" #include "mesh_opaque_fs.h" #include "mesh_vs.h" +#include "mesh_tcs.h" +#include "mesh_tev.h" } // namespace using Avogadro::Vector3f; @@ -49,9 +51,10 @@ class MeshGeometry::Private inline static Shader* vertexShader = nullptr; inline static Shader* fragmentShader = nullptr; inline static Shader* fragmentShaderOpaque = nullptr; + inline static Shader* TessellationControlShader = nullptr; + inline static Shader* TessellationEvaluationShader = nullptr; inline static ShaderProgram* program = nullptr; inline static ShaderProgram* programOpaque = nullptr; - size_t numberOfVertices; size_t numberOfIndices; }; @@ -105,26 +108,59 @@ void MeshGeometry::update() d->fragmentShaderOpaque->setType(Shader::Fragment); d->fragmentShaderOpaque->setSource(mesh_opaque_fs); + d->TessellationControlShader = new Shader; + d->TessellationControlShader->setType(Shader::TessellationControl); + d->TessellationControlShader->setSource(mesh_tcs); + + d->TessellationEvaluationShader = new Shader; + d->TessellationEvaluationShader->setType(Shader::TessellationEvaluation); + d->TessellationEvaluationShader->setSource(mesh_tev); + 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->TessellationControlShader->compile()){ + cout << d->TessellationControlShader->error() << endl; + }else{ + cout << "Success tess-control-shader" <TessellationEvaluationShader->compile()){ + cout << d->TessellationEvaluationShader->error() << endl; + }else{ + cout << "Success tess-evaluation-shader" <program == nullptr) d->program = new ShaderProgram; d->program->attachShader(*d->vertexShader); + d->program->attachShader(*d->TessellationControlShader); + d->program->attachShader(*d->TessellationEvaluationShader); d->program->attachShader(*d->fragmentShader); - if (!d->program->link()) + if (!d->program->link()){ cout << d->program->error() << endl; + }else{ + cout << "shader program linked non-opaque" << endl; + } + if (d->programOpaque == nullptr) d->programOpaque = new ShaderProgram; d->programOpaque->attachShader(*d->vertexShader); + d->programOpaque->attachShader(*d->TessellationControlShader); + d->programOpaque->attachShader(*d->TessellationEvaluationShader); d->programOpaque->attachShader(*d->fragmentShaderOpaque); - if (!d->programOpaque->link()) + if (!d->programOpaque->link()){ cout << d->programOpaque->error() << endl; + }else{ + cout << "shader program linked" << endl; + } + + /* + will create shader program for tessellation shader + */ } } @@ -157,13 +193,15 @@ void MeshGeometry::render(const Camera& camera) ShaderProgram::NoNormalize)) { cout << program->error() << endl; } + if (!program->enableAttributeArray("color")) - cout << program->error() << endl; + cout << program->error() << endl; if (!program->useAttributeArray("color", PackedVertex::colorOffset(), sizeof(PackedVertex), UCharType, 4, ShaderProgram::Normalize)) { cout << program->error() << endl; } + if (!program->enableAttributeArray("normal")) cout << program->error() << endl; if (!program->useAttributeArray("normal", PackedVertex::normalOffset(), @@ -182,17 +220,20 @@ void MeshGeometry::render(const Camera& camera) Matrix3f normalMatrix = camera.modelView().linear().inverse().transpose(); if (!program->setUniformValue("normalMatrix", normalMatrix)) std::cout << program->error() << std::endl; + - // Render the loaded spheres using the shader and bound VBO. - glDrawRangeElements(GL_TRIANGLES, 0, - static_cast(d->numberOfVertices - 1), - static_cast(d->numberOfIndices), GL_UNSIGNED_INT, - reinterpret_cast(0)); + GLint MaxPatchVertices = 0; + glGetIntegerv(GL_MAX_PATCH_VERTICES, &MaxPatchVertices); + cout << "max supported patch" << MaxPatchVertices << endl; + + glPatchParameteri(GL_PATCH_VERTICES, 3); + glDrawElements(GL_PATCHES, static_cast(d->numberOfIndices), + GL_UNSIGNED_INT, reinterpret_cast(0)); d->vbo.release(); d->ibo.release(); - program->disableAttributeArray("vector"); + program->disableAttributeArray("vertex"); program->disableAttributeArray("color"); program->disableAttributeArray("normal"); @@ -291,4 +332,4 @@ void MeshGeometry::clear() m_dirty = true; } -} // End namespace Avogadro +} // End namespace Avogadro \ No newline at end of file diff --git a/avogadro/rendering/shader.cpp b/avogadro/rendering/shader.cpp index e07d79db60..8889303af2 100644 --- a/avogadro/rendering/shader.cpp +++ b/avogadro/rendering/shader.cpp @@ -41,7 +41,25 @@ bool Shader::compile() m_handle = 0; } - GLenum type_ = m_type == Vertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER; +GLenum type_; +switch (m_type) { + case Vertex: + type_ = GL_VERTEX_SHADER; + break; + case Fragment: + type_ = GL_FRAGMENT_SHADER; + break; + case TessellationControl: + type_ = GL_TESS_CONTROL_SHADER; + break; + case TessellationEvaluation: + type_ = GL_TESS_EVALUATION_SHADER; + break; + default: + m_error = "Unknown shader type."; + return false; +} + GLuint handle_ = glCreateShader(type_); const auto* source_ = static_cast(m_source.c_str()); glShaderSource(handle_, 1, &source_, nullptr); diff --git a/avogadro/rendering/shader.h b/avogadro/rendering/shader.h index 493d32e13b..f94f22c9d5 100644 --- a/avogadro/rendering/shader.h +++ b/avogadro/rendering/shader.h @@ -31,6 +31,8 @@ class AVOGADRORENDERING_EXPORT Shader { Vertex, /**< Vertex shader */ Fragment, /**< Fragment shader */ + TessellationControl, + TessellationEvaluation, Unknown /**< Unknown (default) */ }; diff --git a/avogadro/rendering/shaderprogram.cpp b/avogadro/rendering/shaderprogram.cpp index 033c5045a5..ffb992b4d1 100644 --- a/avogadro/rendering/shaderprogram.cpp +++ b/avogadro/rendering/shaderprogram.cpp @@ -84,7 +84,8 @@ inline GLenum lookupTextureUnit(GLint index) } // end anon namespace ShaderProgram::ShaderProgram() - : m_handle(0), m_vertexShader(0), m_fragmentShader(0), m_linked(false) + : m_handle(0), m_vertexShader(0), m_fragmentShader(0), m_linked(false), + m_tcsShader(0), m_tevShader(0) { initializeTextureUnits(); } @@ -129,6 +130,18 @@ bool ShaderProgram::attachShader(const Shader& shader) static_cast(m_fragmentShader)); } m_fragmentShader = shader.handle(); + } else if(shader.type() == Shader::TessellationControl) { + if (m_tcsShader != 0){ + glDetachShader(static_cast(m_handle), + static_cast(m_tcsShader)); + } + m_tcsShader = shader.handle(); + } else if(shader.type() == Shader::TessellationEvaluation) { + if (m_tevShader != 0){ + glDetachShader(static_cast(m_handle), + static_cast(m_tevShader)); + } + m_tevShader = shader.handle(); } else { m_error = "Unknown shader type encountered - this should not happen."; return false; @@ -175,6 +188,26 @@ bool ShaderProgram::detachShader(const Shader& shader) m_fragmentShader = 0; return true; } + case Shader::TessellationControl: + if(m_tcsShader != shader.handle()){ + m_error = "The supplied shader was not attached to this program."; + return false; + } else{ + glDetachShader(static_cast(m_handle), + static_cast(shader.handle())); + m_tcsShader = 0; + return true; + } + case Shader::TessellationEvaluation: + if(m_tevShader != shader.handle()){ + m_error = "The supplied shader was not attached to this program."; + return false; + } else{ + glDetachShader(static_cast(m_handle), + static_cast(shader.handle())); + m_tevShader = 0; + return true; + } default: return false; } diff --git a/avogadro/rendering/shaderprogram.h b/avogadro/rendering/shaderprogram.h index 18330bc7a4..c9b1e13d8d 100644 --- a/avogadro/rendering/shaderprogram.h +++ b/avogadro/rendering/shaderprogram.h @@ -159,6 +159,8 @@ class AVOGADRORENDERING_EXPORT ShaderProgram Index m_handle; Index m_vertexShader; Index m_fragmentShader; + Index m_tcsShader; + Index m_tevShader; bool m_linked;