diff --git a/include/ShaderLib.h b/include/ShaderLib.h index 7ccf8da..1b8378b 100644 --- a/include/ShaderLib.h +++ b/include/ShaderLib.h @@ -40,6 +40,10 @@ class ShaderLib //----------------------------------------------------------------------------------------------------- QOpenGLShaderProgram* getCurrentShader(); +private: + std::string loadFileToString(const std::string &_path); + void parseIncludes(std::string &io_shaderString); + private: enum SHADER_TYPES {VERTEX, FRAGMENT, GEOMETRY, TESSCONTROL, TESSEVAL}; //----------------------------------------------------------------------------------------------------- diff --git a/shaders/include/owl_eye_funcs.h b/shaders/include/owl_eye_funcs.h new file mode 100644 index 0000000..5c968d1 --- /dev/null +++ b/shaders/include/owl_eye_funcs.h @@ -0,0 +1,39 @@ + +mat3 rotationMatrix3d(vec3 axis, float angle) +{ + axis = normalize(axis); + float s = sin(angle); + float c = cos(angle); + float oc = 1.0 - c; + + return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, + oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, + oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c); +} + +vec3 eyePos(vec3 _pos, float scale, vec3 translate, float _twist) +{ + vec3 newPos = _pos; + float stretch = 1.15; + newPos.y *= stretch; + + newPos = newPos/scale - vec3(translate); + + vec3 upVec = vec3(0.0, 0.0, 1.0); + newPos = rotationMatrix3d(upVec, _twist) * newPos; + + return newPos; +} + +float eyeMask(vec3 _pos, float _fuzz, float _cap) +{ + vec2 centre = vec2(0.5); + float dist = distance(centre, _pos.xy); + float mask = 1.0 - smoothstep(_cap - _fuzz, _cap + _fuzz, dist); + return clamp(mask, 0.0, 1.0); +} + +float mask(float _maskA, float _maskB, float _fuzz, float _zDir) +{ + return (_maskA + _maskB) * smoothstep(0.0, _fuzz, _zDir); +} \ No newline at end of file diff --git a/shaders/owl_pbr_geo.glsl b/shaders/owl_pbr_geo.glsl index 90ae0a1..b70f2d4 100644 --- a/shaders/owl_pbr_geo.glsl +++ b/shaders/owl_pbr_geo.glsl @@ -33,6 +33,8 @@ uniform float eyeThickness = 0.08; uniform float eyeGap = 0.19; uniform float eyeFuzz = 0.02; +#include "shaders/include/owl_eye_funcs.h" + // Linear interpolation at between x and y, at t float lerp(float x, float y, float t) { @@ -90,14 +92,21 @@ float eyes(vec3 _posA, vec3 _posB, float fuzz, float gap, float thickness, float void main( void ) { - for(int i=0; i < 3; i++) + for(int i = 0; i < 3; i++) { Normal = normalize(te_normal[i]); TexCoords = te_uv[i]; + vec3 pos = te_position[i]; + float rotation = radians(eyeRotation); + vec3 posA = eyePos(pos, eyeScale, eyeTranslate, rotation); + pos.x *= -1.0; + vec3 posB = eyePos(pos, eyeScale, eyeTranslate, -rotation); + float maskA = eyeMask(posA, eyeFuzz, 0.7); + float maskB = eyeMask(posB, eyeFuzz, 0.7); + float bigMask = mask(maskA, maskB, eyeFuzz, te_normal[i].z); - - float height = eyes(te_posA[i], te_posB[i], eyeFuzz, eyeGap, eyeThickness, eyeWarp, eyeExponent, te_maskA[i], te_maskB[i]) * te_bigMask[i]; + float height = eyes(posA, posB, eyeFuzz, eyeGap, eyeThickness, eyeWarp, eyeExponent, maskA, maskB) * bigMask; EyeVal = height; diff --git a/shaders/owl_pbr_tess_control.glsl b/shaders/owl_pbr_tess_control.glsl index bdba09e..6687fff 100644 --- a/shaders/owl_pbr_tess_control.glsl +++ b/shaders/owl_pbr_tess_control.glsl @@ -9,74 +9,15 @@ in vec2 v_uv[]; out vec3 tc_position[]; out vec3 tc_normal[]; out vec2 tc_uv[]; -out vec3 tc_posA[]; -out vec3 tc_posB[]; -out float tc_maskA[]; -out float tc_maskB[]; -out float tc_bigMask[]; -uniform int innerTess = 64; -uniform int outerTess = 64; uniform float eyeRotation = 7.0; uniform float eyeScale = 1.55; uniform vec3 eyeTranslate = vec3(0.21, 0.3, 0.0); uniform float eyeFuzz = 0.02; +#include "shaders/include/owl_eye_funcs.h" #define ID gl_InvocationID -mat4 rotationMatrix4d(vec3 axis, float angle) -{ - axis = normalize(axis); - float s = sin(angle); - float c = cos(angle); - float oc = 1.0 - c; - - return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, - oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, - 0.0, 0.0, 0.0, 1.0); -} - -mat3 rotationMatrix3d(vec3 axis, float angle) -{ - axis = normalize(axis); - float s = sin(angle); - float c = cos(angle); - float oc = 1.0 - c; - - return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, - oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c); -} - - -vec3 eyePos(vec3 _pos, float scale, vec3 translate, float _twist) -{ - vec3 newPos = _pos; - float stretch = 1.15; - newPos.y *= stretch; - - newPos = newPos/scale - vec3(translate); - - vec3 upVec = vec3(0.0, 0.0, 1.0); - newPos = rotationMatrix3d(upVec, _twist) * newPos; - - return newPos; -} - -float eyeMask(vec3 _pos, float _fuzz) -{ - vec2 centre = vec2(0.5); - float dist = distance(centre, _pos.xy); - float cap = 0.7; - float mask = 1.0 - smoothstep(cap - _fuzz, cap + _fuzz, dist); - return clamp(mask, 0.0, 1.0); -} - -float mask(float _maskA, float _maskB, float _fuzz, float _zDir) -{ - return (_maskA + _maskB) * smoothstep(0.0, 0.0 + _fuzz, _zDir); -} void main(void) { @@ -86,26 +27,21 @@ void main(void) pos.x *= -1.0; vec3 posB = eyePos(pos, eyeScale, eyeTranslate, -rotation); - tc_posA[ID] = posA; - tc_posB[ID] = posB; - float maskA = eyeMask(posA, eyeFuzz); - float maskB = eyeMask(posB, eyeFuzz); - tc_maskA[ID] = maskA; - tc_maskB[ID] = maskB; + float maskA = eyeMask(posA, eyeFuzz, 0.7); + float maskB = eyeMask(posB, eyeFuzz, 0.7); float bigMask = mask(maskA, maskB, eyeFuzz, v_normal[ID].z); - tc_bigMask[ID] = bigMask; tc_position[ID] = v_position[ID]; tc_normal[ID] = v_normal[ID]; tc_uv[ID] = v_uv[ID]; - int tessLevel = 1 + int(ceil(64 * smoothstep(0.0, 1.0, bigMask))); -// if(ID == 0) -// { - gl_TessLevelInner[ID] = tessLevel; - gl_TessLevelOuter[ID * 3] = tessLevel; - gl_TessLevelOuter[ID * 3 + 1] = tessLevel; - gl_TessLevelOuter[ID * 3 + 2] = tessLevel; -// } + float tessMask = mask(eyeMask(posA, eyeFuzz, 1.0), eyeMask(posB, eyeFuzz, 1.0), eyeFuzz, v_normal[ID].z); + int tessLevel = 1 + int(ceil(64 * smoothstep(0.0, 1.0, tessMask))); + + gl_TessLevelInner[0] = tessLevel; + gl_TessLevelOuter[0] = tessLevel; + gl_TessLevelOuter[1] = tessLevel; + gl_TessLevelOuter[2] = tessLevel; + } diff --git a/shaders/owl_pbr_tess_eval.glsl b/shaders/owl_pbr_tess_eval.glsl index 54fe6cd..ea26172 100644 --- a/shaders/owl_pbr_tess_eval.glsl +++ b/shaders/owl_pbr_tess_eval.glsl @@ -5,20 +5,10 @@ layout(triangles, equal_spacing, cw) in; in vec3 tc_position[]; in vec3 tc_normal[]; in vec2 tc_uv[]; -in vec3 tc_posA[]; -in vec3 tc_posB[]; -in float tc_maskA[]; -in float tc_maskB[]; -in float tc_bigMask[]; out vec3 te_position; out vec3 te_normal; out vec2 te_uv; -out vec3 te_posA; -out vec3 te_posB; -out float te_maskA; -out float te_maskB; -out float te_bigMask; uniform mat4 MVP; @@ -27,10 +17,5 @@ void main(void) te_normal = (gl_TessCoord.x * tc_normal[0] + gl_TessCoord.y * tc_normal[1] + gl_TessCoord.z * tc_normal[2]); te_uv = (gl_TessCoord.x * tc_uv[0] + gl_TessCoord.y * tc_uv[1] + gl_TessCoord.z * tc_uv[2]); te_position = (gl_TessCoord.x * tc_position[0] + gl_TessCoord.y * tc_position[1] + gl_TessCoord.z * tc_position[2]); - te_posA = (gl_TessCoord.x * tc_posA[0] + gl_TessCoord.y * tc_posA[1] + gl_TessCoord.z * tc_posA[2]); - te_posB = (gl_TessCoord.x * tc_posB[0] + gl_TessCoord.y * tc_posB[1] + gl_TessCoord.z * tc_posB[2]); - te_maskA = (gl_TessCoord.x * tc_maskA[0] + gl_TessCoord.y * tc_maskA[1] + gl_TessCoord.z * tc_maskA[2]); - te_maskB = (gl_TessCoord.x * tc_maskB[0] + gl_TessCoord.y * tc_maskB[1] + gl_TessCoord.z * tc_maskB[2]); - te_bigMask = (gl_TessCoord.x * tc_bigMask[0] + gl_TessCoord.y * tc_bigMask[1] + gl_TessCoord.z * tc_bigMask[2]); gl_Position = MVP * vec4(te_position, 1.0); } diff --git a/src/DemoScene.cpp b/src/DemoScene.cpp index e387949..057b1d8 100644 --- a/src/DemoScene.cpp +++ b/src/DemoScene.cpp @@ -57,8 +57,6 @@ void DemoScene::initGeo() // Create and bind our Vertex Buffer Object m_meshVBO.init(); generateNewGeometry(); - - context()->versionFunctions()->glPatchParameteri(GL_PATCH_VERTICES, 3); } //----------------------------------------------------------------------------------------------------- void DemoScene::keyPress(QKeyEvent* io_event) diff --git a/src/MaterialPBR.cpp b/src/MaterialPBR.cpp index 329eedb..d7d4df8 100644 --- a/src/MaterialPBR.cpp +++ b/src/MaterialPBR.cpp @@ -1,11 +1,13 @@ #include "MaterialPBR.h" #include "Scene.h" #include "ShaderLib.h" +#include void MaterialPBR::init() { auto shaderPtr = m_shaderLib->getCurrentShader(); + shaderPtr->setPatchVertexCount(3); shaderPtr->setUniformValue("albedo", QVector3D{m_albedo.x, m_albedo.y, m_albedo.z}); shaderPtr->setUniformValue("ao", m_ao); shaderPtr->setUniformValue("exposure", m_exposure); diff --git a/src/ShaderLib.cpp b/src/ShaderLib.cpp index 7856c55..cb594c7 100644 --- a/src/ShaderLib.cpp +++ b/src/ShaderLib.cpp @@ -2,6 +2,10 @@ #include #include #include +#include +#include +#include +#include std::string ShaderLib::loadShaderProg(const QString &_jsonFileName) { @@ -52,7 +56,10 @@ void ShaderLib::createShader(const std::string &_name, const std::arraycompileSourceFile(path); + std::string shaderString = loadFileToString(stdPath); + parseIncludes(shaderString); + + shad->compileSourceCode(shaderString.c_str()); m_shaderParts[stdPath].reset(shad); } program->addShader(m_shaderParts[stdPath].get()); @@ -61,6 +68,77 @@ void ShaderLib::createShader(const std::string &_name, const std::array +std::basic_string regex_replace(BidirIt _first, BidirIt _last, const std::basic_regex& _re, UnaryFunction _f) +{ + std::basic_string s; + + typename std::match_results::difference_type positionOfLastMatch = 0; + auto endOfLastMatch = _first; + + auto callback = [&](const std::match_results& match) + { + auto positionOfThisMatch = match.position(0); + auto diff = positionOfThisMatch - positionOfLastMatch; + + auto startOfThisMatch = endOfLastMatch; + std::advance(startOfThisMatch, diff); + + s.append(endOfLastMatch, startOfThisMatch); + s.append(_f(match)); + + auto lengthOfMatch = match.length(0); + + positionOfLastMatch = positionOfThisMatch + lengthOfMatch; + + endOfLastMatch = startOfThisMatch; + std::advance(endOfLastMatch, lengthOfMatch); + }; + + std::regex_iterator begin(_first, _last, _re), end; + std::for_each(begin, end, callback); + + s.append(endOfLastMatch, _last); + + return s; +} + +template +std::string regex_replace(const std::string& s, const std::basic_regex& re, UnaryFunction f) +{ + return regex_replace(s.cbegin(), s.cend(), re, f); +} + +} // namespace std + +std::string ShaderLib::loadFileToString(const std::string &_path) +{ + std::string ret; + std::ifstream shaderFileStream(_path); + shaderFileStream.seekg(0, std::ios::end); + ret.reserve(shaderFileStream.tellg()); + shaderFileStream.seekg(0, std::ios::beg); + + ret.assign((std::istreambuf_iterator(shaderFileStream)), std::istreambuf_iterator()); + return ret; +} + +void ShaderLib::parseIncludes(std::string &io_shaderString) +{ + std::regex matcher(R"(#{1}include\ +(\"|\<)[a-zA-Z][a-zA-Z0-9_\/]+\.(h|glsl)(\"|\>))"); + io_shaderString = std::regex_replace(io_shaderString, matcher, [this](const std::smatch& _m) + { + auto str = _m.str(); + auto begin = str.find('"') + 1; + auto end = str.find_last_of('"'); + return loadFileToString(std::string(str.begin() + begin, str.begin() + end)); + } + ); +} + void ShaderLib::useShader(const std::string& _name) { m_currentShader = m_shaderPrograms[_name].get();