shader.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #ifndef SHADER_H
  2. #define SHADER_H
  3. #include "vector3D.h"
  4. #include "matrix.h"
  5. #include "texture.h"
  6. #include <array>
  7. //Shader Interface for a class that emulates modern GPU fragment and vertex shaders
  8. struct IShader {
  9. virtual ~IShader() {};
  10. virtual Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals, const Vector3f &tangent, const Vector3f &biTangent, const Vector3f &light, int index) = 0;
  11. virtual Vector3f fragment(float u, float v) = 0;
  12. };
  13. //Simplest shader. Calculates light intensity per triangle.
  14. struct FlatShader : public IShader {
  15. Matrix4 MVP, MV;
  16. float varIntensity;
  17. Vector3f rgb{255,255,255};
  18. Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
  19. varIntensity = std::max(0.0f,normal.dotProduct(light));
  20. return MVP.matMultVec(vertex); //Transforms verts into projected space
  21. }
  22. Vector3f fragment(float u, float v) override{
  23. return rgb*varIntensity;
  24. }
  25. };
  26. //More Complex shader that calculates a per-vertex intensity and interpolates
  27. //through the fragments of the triangle
  28. struct GouraudShader : public IShader {
  29. Matrix4 MVP, MV, V, N;
  30. float ambientStrength = 0.05, diffStrength = 0, specularStrength = 0.5, spec = 0;
  31. Vector3f ambient, diffuse, specular;
  32. Vector3f lightColor1{1,1,1}, lightColor2{0,0,1}, lightColor3{1,1,1};
  33. Vector3f varying_diffuse, varying_specular, reflectDir, viewDir, light2, normal2;
  34. Vector3f rgb{255,255,255};
  35. Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
  36. normal2 = N.matMultDir(normal).normalized();
  37. light2 = V.matMultDir(light).normalized();
  38. reflectDir = Vector3f::reflect(-light2, normal);
  39. viewDir = MV.matMultVec(vertex).normalized();
  40. varying_specular.data[index] = std::pow( std::max( -viewDir.dotProduct(reflectDir), 0.0f), 32.0f);
  41. varying_diffuse.data[index] = std::max(0.0f, (normal).dotProduct(-light2));
  42. return MVP.matMultVec(vertex);
  43. }
  44. Vector3f fragment(float u, float v) override{
  45. ambient = lightColor1 * ambientStrength;
  46. diffStrength = varying_diffuse.x + u*(varying_diffuse.y - varying_diffuse.x) + v*(varying_diffuse.z - varying_diffuse.x);
  47. diffuse = lightColor2 * diffStrength;
  48. spec = varying_specular.x + u*(varying_specular.y - varying_specular.x) + v*(varying_specular.z - varying_specular.x);
  49. specular = lightColor3 * (specularStrength * spec);
  50. return (ambient + diffuse + specular) * rgb;
  51. }
  52. };
  53. //Even more complex shader that interpolates normals and calculates intensities per fragment instead
  54. //instead of per vertex.
  55. struct PhongShader : public IShader {
  56. Matrix4 MVP, MV, V, N;
  57. float ambientStrength = 0.05, diffStrength = 0, specularStrength = 0.9, spec = 0;
  58. Vector3f normals[3], viewDir[3];
  59. Vector3f ambient, diffuse, specular, interpNormal, interpViewDir;
  60. Vector3f lightColor{0,0.1,1},lightColorSpec{1,1,1};
  61. Vector3f varying_diffuse, varying_specular, reflectDir, light2;
  62. Vector3f rgb{255,255,255};
  63. Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
  64. normals[index] = N.matMultDir(normal).normalized();
  65. viewDir[index] = MV.matMultVec(vertex).normalized();
  66. light2 = V.matMultDir(light).normalized();
  67. return MVP.matMultVec(vertex);
  68. }
  69. Vector3f fragment(float u, float v) override{
  70. //Interpolated stuff
  71. interpNormal = normals[0] + (normals[1] - normals[0])* u + (normals[2] - normals[0]) * v;
  72. interpViewDir = viewDir[0] + (viewDir[1] - viewDir[0])* u + (viewDir[2] - viewDir[0]) * v;
  73. //Ambient
  74. ambient = lightColor * ambientStrength;
  75. //Diffuse
  76. diffStrength = std::max(0.0f, (interpNormal.normalized()).dotProduct(light2));
  77. diffuse = lightColor * diffStrength;
  78. //Specular
  79. reflectDir = Vector3f::reflect(-light2, interpNormal);
  80. spec = std::pow( std::max( (-interpViewDir.normalized()).dotProduct(reflectDir), 0.0f), 50.0f);
  81. specular = lightColorSpec * (specularStrength * spec);
  82. return (ambient + diffuse + specular) * rgb;
  83. }
  84. };
  85. //Optimized version of Phong shader that uses a half angle instead of individual reflection
  86. //angles
  87. struct BlinnPhongShader : public IShader {
  88. Texture *albedoT, *normalT;
  89. Matrix4 MVP, MV, V, N;
  90. float ambientStrength = 0.05, diffStrength=1 , specularStrength= 0.5;
  91. float diff, spec, shininess = 128;
  92. Vector3f normals[3], viewDir[3], UV[3];
  93. Vector3f ambient, diffuse, specular, interpNormal, interpViewDir, interpUV;
  94. Vector3f lightColor{1,1,1};
  95. Vector3f halfwayDir, lightDir;
  96. Vector3f interpCol, white{255,255,255};
  97. Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
  98. normals[index] = N.matMultDir(normal).normalized();
  99. UV[index] = textureVals;
  100. viewDir[index] = MV.matMultVec(vertex).normalized();
  101. lightDir = V.matMultDir(light).normalized();
  102. return MVP.matMultVec(vertex);
  103. }
  104. Vector3f fragment(float u, float v) override{
  105. //Interpolated stuff
  106. interpNormal = (normals[0] + (normals[1] - normals[0])* u + (normals[2] - normals[0]) * v).normalized();
  107. interpViewDir = viewDir[0] + (viewDir[1] - viewDir[0])* u + (viewDir[2] - viewDir[0]) * v;
  108. interpUV = UV[0] + (UV[1] - UV[0])* u + (UV[2] - UV[0]) * v;
  109. //Albedo
  110. interpCol = albedoT->getPixelVal(interpUV.x, interpUV.y);
  111. //interpNormal = normalT->getPixelVal(interpUV.x, interpUV.y);
  112. // interpNormal.x = (interpNormal.x*2/256.0f) -1;
  113. // interpNormal.y = (interpNormal.y*2/256.0f) -1;
  114. // interpNormal.z = 1 - interpNormal.z*1/256.0f;
  115. // interpNormal = interpNormal.normalized();
  116. //rgb.print();
  117. //Ambient
  118. ambient = lightColor * ambientStrength;
  119. //Diffuse
  120. diff = std::max(0.0f, interpNormal.dotProduct(lightDir));
  121. diffuse = lightColor * diff * diffStrength;
  122. //Specular
  123. halfwayDir = (lightDir - interpViewDir).normalized();
  124. spec = std::pow(std::max(0.0f, interpNormal.dotProduct(halfwayDir)), shininess);
  125. specular = lightColor * spec * specularStrength;
  126. return (ambient + diffuse) * interpCol + specular * white;
  127. }
  128. };
  129. // Shader that uses normal mapping instead of vertex normal interpolation
  130. struct NormalMapShader : public IShader {
  131. //Variables set per model
  132. Texture *albedoT, *normalT;
  133. Matrix4 MVP, MV, V, M, N;
  134. Vector3f cameraPos;
  135. //Light Variables
  136. Vector3f lightColor{1,1,1}, white{1,1,1};
  137. float ambientStrength = 0.05, diffStrength = 1, specularStrength = 0.5;
  138. float diff, spec, shininess = 128;
  139. //Variables set per vertex
  140. Vector3f normals[3], viewDir[3], UV[3], tangentFragPos[3], viewPos[3];
  141. Vector3f lightDir, vertexPos[3],vertTangent[3], vertBiTangent[3] ;
  142. //Interpolated variables
  143. Vector3f interpUV, interpNormal, interpViewPos, interpCol, interpTangentFragPos;
  144. //Per fragment
  145. Vector3f ambient, diffuse, specular ;
  146. Vector3f halfwayDir;
  147. Vector3f vertex(const Vector3f &vertex, const Vector3f &normal,const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
  148. //Creating TBN matrix
  149. normals[index] = N.matMultDir(normal).normalized();
  150. vertTangent[index] = N.matMultDir(tangent).normalized();
  151. vertBiTangent[index] = N.matMultDir(biTangent).normalized();
  152. vertexPos[index] = M.matMultVec(vertex);
  153. // Matrix4 TBN = Matrix4::TBNMatrix(vertTangent[index], vertBiTangent[index], normals[index]);
  154. //Getting UV coordinates for use in both albedo and normal textures
  155. UV[index] = textureVals;
  156. //Passing all lighting related data to tangent space
  157. // tangentFragPos[index] = TBN.matMultVec(N.matMultVec(vertex));
  158. // viewPos[index] = TBN.matMultVec(cameraPos);
  159. // lightDir = TBN.matMultVec(light);
  160. return MVP.matMultVec(vertex);
  161. }
  162. Vector3f fragment(float u, float v) override{
  163. //Interpolated stuff
  164. // interpTangentFragPos = tangentFragPos[0] + (tangentFragPos[1] - tangentFragPos[0])* u + (tangentFragPos[2] - tangentFragPos[0]) * v;
  165. // interpViewPos = viewPos[0] + (viewPos[1] - viewPos[0])* u + (viewPos[2] - viewPos[0]) * v;
  166. //interpUV = UV[0] + (UV[1] - UV[0])* u + (UV[2] - UV[0]) * v;
  167. Vector3f interpPos = vertexPos[0] + (vertexPos[1] - vertexPos[0])* u + (vertexPos[2] - vertexPos[0]) * v;
  168. Vector3f interpTan = vertTangent[0] + (vertTangent[1] - vertTangent[0])* u + (vertTangent[2] - vertTangent[0]) * v;
  169. Vector3f interpBiTan = vertBiTangent[0] + (vertBiTangent[1] - vertBiTangent[0])* u + (vertBiTangent[2] - vertBiTangent[0]) * v;
  170. Vector3f interpNorm = normals[0] + (normals[1] - normals[0])* u + (normals[2] - normals[0]) * v;
  171. //Albedo
  172. // interpCol = albedoT->getPixelVal(interpUV.x, interpUV.y);
  173. // interpNormal = normalT->getPixelVal(interpUV.x, interpUV.y);
  174. // interpNormal.x = (interpNormal.x * 2/256.0f) - 1;
  175. // interpNormal.y = (interpNormal.y * 2/256.0f) - 1;
  176. // interpNormal.z = (interpNormal.z * 2/256.0f) - 1;
  177. // interpNormal = interpNormal.normalized();
  178. //Ambient
  179. // ambient = lightColor * ambientStrength;
  180. //Diffuse
  181. //lightDir = (interpTangentFragPos - lightDir).normalized();
  182. // diff = std::max(0.0f, interpNormal.dotProduct(lightDir));
  183. // diffuse = lightColor * diff * diffStrength;
  184. //Specular
  185. // halfwayDir = (lightDir - interpViewDir).normalized();
  186. // spec = std::pow(std::max(0.0f, interpNormal.dotProduct(halfwayDir)), shininess);
  187. // specular = lightColor * spec * specularStrength;
  188. //return (ambient + diffuse) * interpCol + specular * white;
  189. return interpPos;
  190. }
  191. };
  192. #endif