Project Description
A small collection of shaders that showcase a variety of the more common techniques related to lighting. The shaders were made as part of an introduction to shader programming both in terms of how to make the shaders and the different techniques as well as how to apply them to a model and how to manage applying parameters and such.
The shaders are made in Nvidia’s CgFX language and the implementation of the framework is done in a self made OpenGL framework with FreeGlut. The framework is set up in a way to efficiently create and apply a shader and apply it to a model and to easily apply and adjust the needed parameters.
Model credit goes to Dmitri Parkin.
Code Snippits
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
#ifndef _EFFECT_H_ #define _EFFECT_H_ #include "Cg/cgGL.h" #include <string> #include <vector> class Effect { public: virtual ~Effect(); static Effect* Create(const std::string& a_Name, const std::string& a_File); const std::string& GetName() const {return m_Name;} bool Load(const std::string& a_File); bool Reload(); CGpass GetFirstPass(); CGpass GetNextPass(); CGpass GetCurrentPass() const { return m_CurrentPass; } CGtechnique GetTechnique() const { return m_Technique; } CGtechnique GetTechnique(const char* a_Name); CGeffect GetCGEffect() const { return m_Effect; } void UpdatePassParameters(); void SetCurrentTechnique(CGtechnique a_Technique) {m_Technique = a_Technique;} CGparameter GetParameter(const char* param); void SetParameter1f(const char* param, float val); void SetParameter2f(const char* param, const float* val); void SetParameter3f(const char* param, const float* val); void SetParameter4f(const char* param, const float* val); void SetParameter1i(const char* param, int val); void SetParameter2i(const char* param, const int* val); void SetParameter3i(const char* param, const int* val); void SetParameter4i(const char* param, const int* val); void SetParameter1d(const char* param, double val); void SetParameter2d(const char* param, const double* val); void SetParameter3d(const char* param, const double* val); void SetParameter4d(const char* param, const double* val); void SetParameterMatrix(const char* param, const float* val); void SetParameterTexture(const char* param, unsigned int texture); void Bind(); void Unbind(); protected: Effect(const std::string& a_Name, const std::string& a_File); std::string m_Name; std::string m_File; CGeffect m_Effect; CGtechnique m_Technique; CGpass m_CurrentPass; std::vector<CGtechnique> m_TechniqueList; static CGcontext m_Context; }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
#ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> // For OutputDebugString #endif #include <sstream> #include "Effect.h" #include <string> CGcontext Effect::m_Context = NULL; // Error handler for Cg void CgErrorHandler( CGcontext context, CGerror error, void* appdata ) { if ( error != CG_NO_ERROR ) { std::stringstream ss; const char* pStr = cgGetErrorString(error); std::string strError = ( pStr == NULL ) ? "" : pStr; ss << "Cg ERROR: " << strError << std::endl; std::string strListing; if ( error == CG_COMPILER_ERROR ) { pStr = cgGetLastListing( context ); strListing = ( pStr == NULL ) ? "" : pStr; ss << strListing << std::endl; } #ifdef _WIN32 OutputDebugStringA( ss.str().c_str() ); #else std::cerr << ss; #endif } } Effect::Effect( const std::string& a_Name, const std::string& a_File ) { m_Name = a_Name; m_File = a_File; m_CurrentPass = NULL; if(!m_Context) { m_Context = cgCreateContext(); cgSetErrorHandler(&CgErrorHandler, NULL); cgGLRegisterStates(m_Context); cgGLSetManageTextureParameters(m_Context, CG_TRUE); } Load(a_File); } Effect::~Effect() { if(m_Effect != NULL) { cgDestroyEffect(m_Effect); m_Effect = NULL; } if(m_Context != NULL) { cgDestroyContext(m_Context); m_Context = NULL; } cgSetErrorHandler(NULL, NULL); } Effect* Effect::Create( const std::string& a_Name, const std::string& a_File ) { Effect* effect = new Effect(a_Name, a_File); return effect; } bool Effect::Load( const std::string& a_File ) { m_Effect = cgCreateEffectFromFile(m_Context, a_File.c_str(), NULL); if(m_Effect == NULL) { exit(-1); } CGtechnique technique = cgGetFirstTechnique(m_Effect); while(technique != NULL) { m_Technique = technique; m_TechniqueList.push_back(technique); technique = cgGetNextTechnique(technique); } if(!m_Technique) { exit(-1); } return true; } bool Effect::Reload() { cgDestroyEffect(m_Effect); m_TechniqueList.clear(); Load(m_File); return true; } CGpass Effect::GetFirstPass() { m_CurrentPass = cgGetFirstPass(m_Technique); return m_CurrentPass; } CGpass Effect::GetNextPass() { m_CurrentPass = cgGetNextPass(m_CurrentPass); return m_CurrentPass; } void Effect::UpdatePassParameters() { cgUpdatePassParameters(m_CurrentPass); } CGparameter Effect::GetParameter( const char* param ) { CGparameter p = cgGetEffectParameterBySemantic(m_Effect, param); if(p) return p; p = cgGetNamedEffectParameter(m_Effect, param); if(p) return p; return 0; } void Effect::SetParameter1f( const char* param, float val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter1f(parameter, val); } void Effect::SetParameter2f( const char* param, const float* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter2f(parameter, val[0], val[1]); } void Effect::SetParameter3f( const char* param, const float* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter3f(parameter, val[0], val[1], val[2]); } void Effect::SetParameter4f( const char* param, const float* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter4f(parameter, val[0], val[1], val[2], val[3]); } void Effect::SetParameter1i( const char* param, int val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter1i(parameter, val); } void Effect::SetParameter2i( const char* param, const int* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter2i(parameter, val[0], val[1]); } void Effect::SetParameter3i( const char* param, const int* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter3i(parameter, val[0], val[1], val[2]); } void Effect::SetParameter4i( const char* param, const int* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter4i(parameter, val[0], val[1], val[3], val[4]); } void Effect::SetParameter1d( const char* param, double val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter1d(parameter, val); } void Effect::SetParameter2d( const char* param, const double* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter2d(parameter, val[0], val[1]); } void Effect::SetParameter3d( const char* param, const double* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter3d(parameter, val[0], val[1], val[2]); } void Effect::SetParameter4d( const char* param, const double* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetParameter4d(parameter, val[0], val[1], val[3], val[4]); } void Effect::SetParameterMatrix( const char* param, const float* val ) { CGparameter parameter = GetParameter(param); if(parameter) cgSetMatrixParameterfc(parameter, val); } void Effect::SetParameterTexture( const char* param, unsigned int texture ) { CGparameter parameter = GetParameter(param); if(parameter) cgGLSetTextureParameter(parameter, texture); } void Effect::Bind() { cgSetPassState(m_CurrentPass); } void Effect::Unbind() { cgResetPassState(m_CurrentPass); } CGtechnique Effect::GetTechnique( const char* a_Name ) { for(int i = 0; i < m_TechniqueList.size(); ++i) { const char* name = cgGetTechniqueName(m_TechniqueList[i]); if(strcmp(name, a_Name) != 1) return m_TechniqueList[i]; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
float Attenuation(float4 p, _Light light) { float d = distance(p, light.Position); return 1 / (light.ConstantAttenuation + light.LinearAttenuation * d + light.QuadraticAttenuation * d * d); } float4 expand(float4 v) { return (v-0.5)*2; } float4 CalcLambert(float3 position, float3 normal, _Light light) { float3 L = normalize(light.Position - position); float A = Attenuation(float4(position, 0), light); float D = saturate(dot(normal, L)); return light.Color * D * A; } float4 CalcSpecularity(float3 position, float3 normal, float shine, _Light light) { float3 L = normalize(light.Position - position); float3 V = normalize(EyePosition - position); float3 H = normalize(L + V); float A = Attenuation(float4(position, 0), light); float S = pow(max(dot(normal, H), 0), shine); return light.Color * S * A; } float tex2Dshadow( sampler2D shadowMap, float4 texCoord ) { float4 projTexColor = tex2Dproj( shadowMap, texCoord ); float test = texCoord.z / texCoord.w; float val = ( test < ( projTexColor.r ) ) ? 1.0f : 0.0f; // Don't shade pixels that are behind the light. return ( texCoord.w < 0 ) ? 1.0f : val; } float dualConeSpotlight(float3 P, _Light light) { float3 V = normalize(P - light.Position); float cosOuterCone = light.OuterCosAngle; float cosInnerCone = light.InnerCosAngle; float cosDirection = dot(V, light.Direction); return smoothstep(cosOuterCone, cosInnerCone, cosDirection); } void SpotAttenLighting( _Light light, float3 P, float3 N, float3 eyePosition, float shininess, out float4 diffuseResult, out float4 specularResult) { // Compute spotlight effect float spotEffect = dualConeSpotlight(P, light); float4 lambert = CalcLambert(P, N, light); float4 phong = CalcSpecularity(P, N, shininess, light); diffuseResult = lambert * spotEffect; specularResult = phong * spotEffect; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#include "General.header" #include "Functions.header" void mainVP(in Vertex IN, out Fragment OUT) { OUT.pos = mul(ModelViewProjection, float4(IN.pos, 1)); OUT.wpos = mul(ModelMatrix, float4(IN.pos, 1)); float3 worldnormal = normalize(mul(ModelMatrixIT, IN.normal)); float3 worldbinormal = normalize(mul(ModelMatrixIT, IN.binormal)); float3 worldtangent = normalize(mul(ModelMatrixIT, IN.tangent)); OUT.normal = float4(worldnormal, 1.0); OUT.binormal = float4(worldbinormal, 1.0); OUT.tangent = float4(worldtangent, 1.0); OUT.uv = IN.uv; OUT.diffuse = IN.diffuse; } void mainFP( in Fragment IN, out float4 color : COLOR) { float4 normalTex = tex2D(g_normalmap, IN.uv); float4 diffuse = Material.Diffuse;; float4 specular = Material.Specular; float4 emissive = Material.Emissive; if(Material.DiffuseMap != 0) { diffuse = tex2D(g_DiffuseMap, IN.uv); } if(Material.SpecularMap != 0) { specular = tex2D(g_specularmap, IN.uv); } if(Material.EmissiveMap != 0) { emissive = tex2D(g_emissivemap, IN.uv); } float4x4 tbnmatrix; tbnmatrix[0] = IN.tangent; tbnmatrix[1] = IN.binormal; tbnmatrix[2] = IN.normal; float4 normalSample = expand(normalTex); normalSample = mul(normalSample, tbnmatrix); float4 lambert; float4 phong; if(Material.NormalMap != 0) { lambert = CalcLambert(IN.wpos.xyz, normalSample.xyz, Light); phong = CalcSpecularity(IN.wpos.xyz, normalSample.xyz, Material.Shininess, Light); } else { lambert = CalcLambert(IN.wpos.xyz, IN.normal, Light); phong = CalcSpecularity(IN.wpos.xyz, IN.normal, Material.Shininess, Light); } float4 ambientfinal = GlobalAmbient * Material.Ambient; float4 diffusefinal = lambert * diffuse; float4 specularfinal = phong * specular; float4 emissivefinal = emissive; color = ambientfinal + emissivefinal + (diffusefinal + specularfinal); } technique t0 { pass p0 { VertexProgram = compile arbvp1 mainVP(); FragmentProgram = compile arbfp1 mainFP(); } } |