| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- // Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include "shaders/MsBsCommon.glsl"
- layout(vertices = 3) out;
- // Defines
- #define IID gl_InvocationID
- #define IN_POS4(i_) gl_in[i_].gl_Position
- #define IN_POS3(i_) gl_in[i_].gl_Position.xyz
- #define OUT_POS4(i_) gl_out[i_].gl_Position
- //
- // In
- //
- in gl_PerVertex
- {
- vec4 gl_Position;
- }
- gl_in[];
- layout(location = 0) in vec2 inTexCoords[];
- layout(location = 1) in mediump vec3 inNormal[];
- #if PASS == COLOR
- layout(location = 2) in mediump vec4 inTangent[];
- #endif
- #if INSTANCE_ID_FRAGMENT_SHADER
- layout(location = 3) flat in uint inInstanceId[];
- #endif
- //
- // Out
- //
- out gl_PerVertex
- {
- vec4 gl_Position;
- }
- gl_out[];
- layout(location = 0) out vec2 outTexCoord[];
- layout(location = 1) out vec3 outNormal[];
- #if PASS == COLOR
- layout(location = 2) out vec4 outTangent[];
- #endif
- #if INSTANCE_ID_FRAGMENT_SHADER
- struct CommonPatch
- {
- uint instanceId;
- };
- #endif
- struct PNPatch
- {
- vec3 pos021;
- vec3 pos012;
- vec3 pos102;
- vec3 pos201;
- vec3 pos210;
- vec3 pos120;
- vec3 pos111;
- };
- struct PhongPatch
- {
- vec3 terms[3];
- };
- out patch PNPatch pnPatch;
- out patch PhongPatch phongPatch;
- #if INSTANCE_ID_FRAGMENT_SHADER
- out patch CommonPatch commonPatch;
- #endif
- // Project point to plane
- vec3 projectToPlane(vec3 point, vec3 planePoint, vec3 planeNormal)
- {
- vec3 v = point - planePoint;
- float pen = dot(v, planeNormal);
- vec3 d = pen * planeNormal;
- return (point - d);
- }
- // Calculate control points
- void calcPositions()
- {
- // The original vertices stay the same
- vec3 pos030 = IN_POS3(0);
- vec3 pos003 = IN_POS3(1);
- vec3 pos300 = IN_POS3(2);
- OUT_POS4(0) = IN_POS4(0);
- OUT_POS4(1) = IN_POS4(1);
- OUT_POS4(2) = IN_POS4(2);
- // edges are names according to the opposing vertex
- vec3 edgeB300 = pos003 - pos030;
- vec3 edgeB030 = pos300 - pos003;
- vec3 edgeB003 = pos030 - pos300;
- // Generate two midpoints on each edge
- pnPatch.pos021 = pos030 + edgeB300 / 3.0;
- pnPatch.pos012 = pos030 + edgeB300 * 2.0 / 3.0;
- pnPatch.pos102 = pos003 + edgeB030 / 3.0;
- pnPatch.pos201 = pos003 + edgeB030 * 2.0 / 3.0;
- pnPatch.pos210 = pos300 + edgeB003 / 3.0;
- pnPatch.pos120 = pos300 + edgeB003 * 2.0 / 3.0;
- pnPatch.pos021 = projectToPlane(pnPatch.pos021, pos030, outNormal[0]);
- pnPatch.pos012 = projectToPlane(pnPatch.pos012, pos003, outNormal[1]);
- pnPatch.pos102 = projectToPlane(pnPatch.pos102, pos003, outNormal[1]);
- pnPatch.pos201 = projectToPlane(pnPatch.pos201, pos300, outNormal[2]);
- pnPatch.pos210 = projectToPlane(pnPatch.pos210, pos300, outNormal[2]);
- pnPatch.pos120 = projectToPlane(pnPatch.pos120, pos030, outNormal[0]);
- // Handle the center
- vec3 center = (pos003 + pos030 + pos300) / 3.0;
- pnPatch.pos111 =
- (pnPatch.pos021 + pnPatch.pos012 + pnPatch.pos102 + pnPatch.pos201 + pnPatch.pos210 + pnPatch.pos120) / 6.0;
- pnPatch.pos111 += (pnPatch.pos111 - center) / 2.0;
- }
- vec3 calcFaceNormal(in vec3 v0, in vec3 v1, in vec3 v2)
- {
- return normalize(cross(v1 - v0, v2 - v0));
- }
- float calcEdgeTessLevel(in vec3 n0, in vec3 n1, in float maxTessLevel)
- {
- vec3 norm = normalize(n0 + n1);
- float tess = (1.0 - norm.z) * (maxTessLevel - 1.0) + 1.0;
- return tess;
- }
- /*float calcEdgeTessLevel(in vec2 p0, in vec2 p1, in float maxTessLevel)
- {
- float dist = distance(p0, p1) * 10.0;
- return dist * (maxTessLevel - 1.0) + 1.0;
- }*/
- // Given the face positions in NDC caclulate if the face is front facing or not
- bool isFaceFrontFacing(in vec2 posNdc[3])
- {
- vec2 a = posNdc[1] - posNdc[0];
- vec2 b = posNdc[2] - posNdc[1];
- vec2 c = a.xy * b.yx;
- return (c.x - c.y) > 0.0;
- }
- // Check if a single NDC position is outside the clip space
- bool posOutsideClipSpace(in vec2 posNdc)
- {
- bvec2 compa = lessThan(posNdc, vec2(-1.0));
- bvec2 compb = greaterThan(posNdc, vec2(1.0));
- return all(bvec4(compa, compb));
- }
- // Check if a face in NDC is outside the clip space
- bool isFaceOutsideClipSpace(in vec2 posNdc[3])
- {
- return any(bvec3(posOutsideClipSpace(posNdc[0]), posOutsideClipSpace(posNdc[1]), posOutsideClipSpace(posNdc[2])));
- }
- // Check if a face is visible
- bool isFaceVisible(in mat4 mvp)
- {
- // Calculate clip positions
- vec2 clip[3];
- for(int i = 0; i < 3; i++)
- {
- vec4 v = mvp * IN_POS4(i);
- clip[i] = v.xy / (v.w * 0.5 + 0.5);
- }
- // Check the face orientation and clipping
- return isFaceFrontFacing(clip) && !isFaceOutsideClipSpace(clip);
- }
- void setSilhouetteTessLevels(in mat3 normalMat, in float maxTessLevel)
- {
- // Calculate the normals in view space
- vec3 nv[3];
- for(int i = 0; i < 3; i++)
- {
- nv[i] = normalMat * inNormal[i];
- }
- gl_TessLevelOuter[0] = calcEdgeTessLevel(nv[1], nv[2], maxTessLevel);
- gl_TessLevelOuter[1] = calcEdgeTessLevel(nv[2], nv[0], maxTessLevel);
- gl_TessLevelOuter[2] = calcEdgeTessLevel(nv[0], nv[1], maxTessLevel);
- gl_TessLevelInner[0] = (gl_TessLevelOuter[0] + gl_TessLevelOuter[1] + gl_TessLevelOuter[2]) / 3.0;
- }
- void setConstantTessLevels(in float maxTessLevel)
- {
- gl_TessLevelOuter[0] = maxTessLevel;
- gl_TessLevelOuter[1] = maxTessLevel;
- gl_TessLevelOuter[2] = maxTessLevel;
- gl_TessLevelInner[0] = maxTessLevel;
- }
- void discardPatch()
- {
- gl_TessLevelOuter[0] = 0.0;
- gl_TessLevelOuter[1] = 0.0;
- gl_TessLevelOuter[2] = 0.0;
- gl_TessLevelInner[0] = 0.0;
- }
- // Used in phong method
- float calcPhongTerm(int ivId, int i, vec3 q)
- {
- vec3 qMinusP = q - IN_POS3(i);
- return q[ivId] - dot(qMinusP, inNormal[i]) * inNormal[i][ivId];
- }
- // This function is part of the point-normal tessellation method
- #define tessellatePNPositionNormalTangentTexCoord_DEFINED
- void tessellatePNPositionNormalTangentTexCoord(in float maxTessLevel, in mat4 mvp, in mat3 normalMat)
- {
- float tessLevel = 0.0;
- // Calculate the face normal in view space
- vec3 faceNorm = calcFaceNormal(IN_POS3(0), IN_POS3(1), IN_POS3(2));
- faceNorm = (normalMat * faceNorm);
- if(faceNorm.z >= 0.0)
- {
- // The face is front facing
- for(int i = 0; i < 3; i++)
- {
- outTexCoord[i] = inTexCoords[i];
- outNormal[i] = inNormal[i];
- #if PASS == COLOR
- outTangent[i] = inTangent[i];
- #endif
- }
- calcPositions();
- // Calculate the tessLevel. It's 1.0 when the normal is facing the cam
- // and maxTessLevel when it's facing away. This gives high tessellation
- // on silhouettes
- tessLevel = (1.0 - faceNorm.z) * (maxTessLevel - 1.0) + 1.0;
- }
- gl_TessLevelOuter[0] = tessLevel;
- gl_TessLevelOuter[1] = tessLevel;
- gl_TessLevelOuter[2] = tessLevel;
- gl_TessLevelInner[0] = tessLevel;
- }
- #define tessellatePhongPositionNormalTangentTexCoord_DEFINED
- void tessellatePhongPositionNormalTangentTexCoord(in float maxTessLevel, in mat4 mvp, in mat3 normalMat)
- {
- if(IID == 0)
- {
- if(isFaceVisible(mvp))
- {
- setSilhouetteTessLevels(normalMat, maxTessLevel);
- }
- else
- {
- discardPatch();
- }
- }
- OUT_POS4(IID) = IN_POS4(IID); // Do that here to trick the barrier
- barrier();
- if(gl_TessLevelOuter[0] > 0.0)
- {
- outTexCoord[IID] = inTexCoords[IID];
- outNormal[IID] = inNormal[IID];
- #if PASS == COLOR
- outTangent[IID] = inTangent[IID];
- #endif
- phongPatch.terms[IID][0] = calcPhongTerm(IID, 0, IN_POS3(1)) + calcPhongTerm(IID, 1, IN_POS3(0));
- phongPatch.terms[IID][1] = calcPhongTerm(IID, 1, IN_POS3(2)) + calcPhongTerm(IID, 2, IN_POS3(1));
- phongPatch.terms[IID][2] = calcPhongTerm(IID, 2, IN_POS3(0)) + calcPhongTerm(IID, 0, IN_POS3(2));
- }
- }
- #define tessellateDispMapPositionNormalTangentTexCoord_DEFINED
- void tessellateDispMapPositionNormalTangentTexCoord(in float maxTessLevel, in mat4 mvp, in mat3 normalMat)
- {
- if(IID == 0)
- {
- if(isFaceVisible(mvp))
- {
- setConstantTessLevels(maxTessLevel);
- #if INSTANCE_ID_FRAGMENT_SHADER
- commonPatch.instanceId = inInstanceId[0];
- #endif
- }
- else
- {
- discardPatch();
- }
- }
- // Passthrough
- OUT_POS4(IID) = IN_POS4(IID);
- outTexCoord[IID] = inTexCoords[IID];
- outNormal[IID] = inNormal[IID];
- #if PASS == COLOR
- outTangent[IID] = inTangent[IID];
- #endif
- }
|