| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- #ifndef SHADER_H
- #define SHADER_H
- #include "vector3D.h"
- #include "matrix.h"
- #include "texture.h"
- #include <array>
- //Shader Interface for a class that emulates modern GPU fragment and vertex shaders
- struct IShader {
- virtual ~IShader() {};
- virtual Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals, const Vector3f &tangent, const Vector3f &biTangent, const Vector3f &light, int index) = 0;
- virtual Vector3f fragment(float u, float v) = 0;
- };
- //Simplest shader. Calculates light intensity per triangle.
- struct FlatShader : public IShader {
- Matrix4 MVP, MV;
- float varIntensity;
- Vector3f rgb{255,255,255};
- Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
- varIntensity = std::max(0.0f,normal.dotProduct(light));
- return MVP.matMultVec(vertex); //Transforms verts into projected space
- }
- Vector3f fragment(float u, float v) override{
- return rgb*varIntensity;
- }
- };
- //More Complex shader that calculates a per-vertex intensity and interpolates
- //through the fragments of the triangle
- struct GouraudShader : public IShader {
- Matrix4 MVP, MV, V, N;
- float ambientStrength = 0.05, diffStrength = 0, specularStrength = 0.5, spec = 0;
- Vector3f ambient, diffuse, specular;
- Vector3f lightColor1{1,1,1}, lightColor2{0,0,1}, lightColor3{1,1,1};
- Vector3f varying_diffuse, varying_specular, reflectDir, viewDir, light2, normal2;
- Vector3f rgb{255,255,255};
- Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
- normal2 = N.matMultDir(normal).normalized();
- light2 = V.matMultDir(light).normalized();
- reflectDir = Vector3f::reflect(-light2, normal);
- viewDir = MV.matMultVec(vertex).normalized();
- varying_specular.data[index] = std::pow( std::max( -viewDir.dotProduct(reflectDir), 0.0f), 32.0f);
- varying_diffuse.data[index] = std::max(0.0f, (normal).dotProduct(-light2));
- return MVP.matMultVec(vertex);
- }
- Vector3f fragment(float u, float v) override{
- ambient = lightColor1 * ambientStrength;
- diffStrength = varying_diffuse.x + u*(varying_diffuse.y - varying_diffuse.x) + v*(varying_diffuse.z - varying_diffuse.x);
- diffuse = lightColor2 * diffStrength;
- spec = varying_specular.x + u*(varying_specular.y - varying_specular.x) + v*(varying_specular.z - varying_specular.x);
- specular = lightColor3 * (specularStrength * spec);
- return (ambient + diffuse + specular) * rgb;
- }
- };
- //Even more complex shader that interpolates normals and calculates intensities per fragment instead
- //instead of per vertex.
- struct PhongShader : public IShader {
- Matrix4 MVP, MV, V, N;
- float ambientStrength = 0.05, diffStrength = 0, specularStrength = 0.9, spec = 0;
- Vector3f normals[3], viewDir[3];
- Vector3f ambient, diffuse, specular, interpNormal, interpViewDir;
- Vector3f lightColor{0,0.1,1},lightColorSpec{1,1,1};
- Vector3f varying_diffuse, varying_specular, reflectDir, light2;
- Vector3f rgb{255,255,255};
- Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
- normals[index] = N.matMultDir(normal).normalized();
- viewDir[index] = MV.matMultVec(vertex).normalized();
- light2 = V.matMultDir(light).normalized();
- return MVP.matMultVec(vertex);
- }
- Vector3f fragment(float u, float v) override{
- //Interpolated stuff
- interpNormal = normals[0] + (normals[1] - normals[0])* u + (normals[2] - normals[0]) * v;
- interpViewDir = viewDir[0] + (viewDir[1] - viewDir[0])* u + (viewDir[2] - viewDir[0]) * v;
- //Ambient
- ambient = lightColor * ambientStrength;
- //Diffuse
- diffStrength = std::max(0.0f, (interpNormal.normalized()).dotProduct(light2));
- diffuse = lightColor * diffStrength;
-
- //Specular
- reflectDir = Vector3f::reflect(-light2, interpNormal);
- spec = std::pow( std::max( (-interpViewDir.normalized()).dotProduct(reflectDir), 0.0f), 50.0f);
- specular = lightColorSpec * (specularStrength * spec);
- return (ambient + diffuse + specular) * rgb;
- }
- };
- //Optimized version of Phong shader that uses a half angle instead of individual reflection
- //angles
- struct BlinnPhongShader : public IShader {
- Texture *albedoT, *normalT;
- Matrix4 MVP, MV, V, N;
- float ambientStrength = 0.05, diffStrength=1 , specularStrength= 0.5;
- float diff, spec, shininess = 128;
- Vector3f normals[3], viewDir[3], UV[3];
- Vector3f ambient, diffuse, specular, interpNormal, interpViewDir, interpUV;
- Vector3f lightColor{1,1,1};
- Vector3f halfwayDir, lightDir;
- Vector3f interpCol, white{255,255,255};
- Vector3f vertex(const Vector3f &vertex, const Vector3f &normal, const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
- normals[index] = N.matMultDir(normal).normalized();
- UV[index] = textureVals;
- viewDir[index] = MV.matMultVec(vertex).normalized();
- lightDir = V.matMultDir(light).normalized();
- return MVP.matMultVec(vertex);
- }
- Vector3f fragment(float u, float v) override{
- //Interpolated stuff
- interpNormal = (normals[0] + (normals[1] - normals[0])* u + (normals[2] - normals[0]) * v).normalized();
- interpViewDir = viewDir[0] + (viewDir[1] - viewDir[0])* u + (viewDir[2] - viewDir[0]) * v;
- interpUV = UV[0] + (UV[1] - UV[0])* u + (UV[2] - UV[0]) * v;
- //Albedo
- interpCol = albedoT->getPixelVal(interpUV.x, interpUV.y);
- //interpNormal = normalT->getPixelVal(interpUV.x, interpUV.y);
- // interpNormal.x = (interpNormal.x*2/256.0f) -1;
- // interpNormal.y = (interpNormal.y*2/256.0f) -1;
- // interpNormal.z = 1 - interpNormal.z*1/256.0f;
- // interpNormal = interpNormal.normalized();
- //rgb.print();
- //Ambient
- ambient = lightColor * ambientStrength;
- //Diffuse
- diff = std::max(0.0f, interpNormal.dotProduct(lightDir));
- diffuse = lightColor * diff * diffStrength;
-
- //Specular
- halfwayDir = (lightDir - interpViewDir).normalized();
- spec = std::pow(std::max(0.0f, interpNormal.dotProduct(halfwayDir)), shininess);
- specular = lightColor * spec * specularStrength;
- return (ambient + diffuse) * interpCol + specular * white;
- }
- };
- // Shader that uses normal mapping instead of vertex normal interpolation
- struct NormalMapShader : public IShader {
- //Variables set per model
- Texture *albedoT, *normalT;
- Matrix4 MVP, MV, V, M, N;
- Vector3f cameraPos;
- //Light Variables
- Vector3f lightColor{1,1,1}, white{1,1,1};
- float ambientStrength = 0.05, diffStrength = 1, specularStrength = 0.5;
- float diff, spec, shininess = 128;
- //Variables set per vertex
- Vector3f normals[3], viewDir[3], UV[3], tangentFragPos[3], viewPos[3];
- Vector3f lightDir, vertexPos[3],vertTangent[3], vertBiTangent[3] ;
-
- //Interpolated variables
- Vector3f interpUV, interpNormal, interpViewPos, interpCol, interpTangentFragPos;
- //Per fragment
- Vector3f ambient, diffuse, specular ;
- Vector3f halfwayDir;
- Vector3f vertex(const Vector3f &vertex, const Vector3f &normal,const Vector3f &textureVals,const Vector3f &tangent,const Vector3f &biTangent,const Vector3f &light, int index) override{
- //Creating TBN matrix
- normals[index] = N.matMultDir(normal).normalized();
- vertTangent[index] = N.matMultDir(tangent).normalized();
- vertBiTangent[index] = N.matMultDir(biTangent).normalized();
- vertexPos[index] = M.matMultVec(vertex);
- // Matrix4 TBN = Matrix4::TBNMatrix(vertTangent[index], vertBiTangent[index], normals[index]);
- //Getting UV coordinates for use in both albedo and normal textures
- UV[index] = textureVals;
- //Passing all lighting related data to tangent space
- // tangentFragPos[index] = TBN.matMultVec(N.matMultVec(vertex));
- // viewPos[index] = TBN.matMultVec(cameraPos);
- // lightDir = TBN.matMultVec(light);
- return MVP.matMultVec(vertex);
- }
- Vector3f fragment(float u, float v) override{
- //Interpolated stuff
- // interpTangentFragPos = tangentFragPos[0] + (tangentFragPos[1] - tangentFragPos[0])* u + (tangentFragPos[2] - tangentFragPos[0]) * v;
- // interpViewPos = viewPos[0] + (viewPos[1] - viewPos[0])* u + (viewPos[2] - viewPos[0]) * v;
- //interpUV = UV[0] + (UV[1] - UV[0])* u + (UV[2] - UV[0]) * v;
- Vector3f interpPos = vertexPos[0] + (vertexPos[1] - vertexPos[0])* u + (vertexPos[2] - vertexPos[0]) * v;
- Vector3f interpTan = vertTangent[0] + (vertTangent[1] - vertTangent[0])* u + (vertTangent[2] - vertTangent[0]) * v;
- Vector3f interpBiTan = vertBiTangent[0] + (vertBiTangent[1] - vertBiTangent[0])* u + (vertBiTangent[2] - vertBiTangent[0]) * v;
- Vector3f interpNorm = normals[0] + (normals[1] - normals[0])* u + (normals[2] - normals[0]) * v;
- //Albedo
- // interpCol = albedoT->getPixelVal(interpUV.x, interpUV.y);
- // interpNormal = normalT->getPixelVal(interpUV.x, interpUV.y);
- // interpNormal.x = (interpNormal.x * 2/256.0f) - 1;
- // interpNormal.y = (interpNormal.y * 2/256.0f) - 1;
- // interpNormal.z = (interpNormal.z * 2/256.0f) - 1;
- // interpNormal = interpNormal.normalized();
- //Ambient
- // ambient = lightColor * ambientStrength;
- //Diffuse
- //lightDir = (interpTangentFragPos - lightDir).normalized();
- // diff = std::max(0.0f, interpNormal.dotProduct(lightDir));
- // diffuse = lightColor * diff * diffStrength;
-
- //Specular
- // halfwayDir = (lightDir - interpViewDir).normalized();
- // spec = std::pow(std::max(0.0f, interpNormal.dotProduct(halfwayDir)), shininess);
- // specular = lightColor * spec * specularStrength;
- //return (ambient + diffuse) * interpCol + specular * white;
- return interpPos;
- }
- };
- #endif
|