Skip to content

Commit 32ce5f1

Browse files
committed
Normal maps can be used to increase the detail in the lighting of a surface.
1 parent f2d279a commit 32ce5f1

File tree

7 files changed

+110
-8
lines changed

7 files changed

+110
-8
lines changed

content/normal.png

2.86 MB
Loading

content/shaders/model.fs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
uniform bool bDiffuse = false;
22
uniform sampler2D iDiffuse;
3+
uniform bool bNormal = false;
4+
uniform sampler2D iNormal;
35
uniform vec4 vecColor = vec4(1.0, 1.0, 1.0, 1.0);
46

7+
uniform bool bLighted;
58
uniform vec3 vecSunlight;
69

710
uniform float flAlpha;
811

912
in vec3 vecFragmentPosition;
1013
in vec2 vecFragmentTexCoord0;
1114
in vec3 vecFragmentNormal;
15+
in vec3 vecFragmentTangent;
16+
in vec3 vecFragmentBitangent;
1217
in vec3 vecFragmentColor;
1318

1419
uniform mat4 mView;
@@ -19,16 +24,41 @@ void main()
1924
// This 3x3 matrix should have the rotation components only. We need it to transform the fragment normals into world space.
2025
mat3 mGlobal3x3 = mat3(mGlobal);
2126

22-
// Transform the local space fragment normal into a global space vector and normalize it.
23-
// http://youtu.be/0zmLe4SssJc
24-
vec3 vecGlobalNormal = normalize(mGlobal3x3*vecFragmentNormal);
27+
vec3 vecGlobalNormal;
28+
if (bNormal)
29+
{
30+
vec3 vecLocalNormal = normalize(texture(iNormal, vecFragmentTexCoord0).xyz * 2.0 - 1.0);
2531

26-
// Dot product of the sunlight vector and the normal vector of this surface.
27-
// http://youtu.be/0zmLe4SssJc
28-
float flLightDot = dot(-vecSunlight, vecGlobalNormal);
32+
// Since vecFragmentTexCoord0.y gets flipped in the vertex shader for texturing reasons,
33+
// we have to flip this normal again to get correct lighting.
34+
vecLocalNormal.y = -vecLocalNormal.y;
2935

30-
// Remap the light values so that they are a little softer
31-
float flLight = RemapVal(flLightDot, 1.0, 0.0, 0.9, 0.4);
36+
// Create a matrix to transform the tangent from texture/triangle space to the object's local space.
37+
// http://youtu.be/TpQudLqiFfU
38+
mat3 mTBN = mat3(vecFragmentTangent, vecFragmentBitangent, vecFragmentNormal);
39+
vecGlobalNormal = normalize(mGlobal3x3*mTBN*vecLocalNormal);
40+
}
41+
else
42+
{
43+
// Transform the local space fragment normal into a global space vector and normalize it.
44+
// http://youtu.be/0zmLe4SssJc
45+
vecGlobalNormal = normalize(mGlobal3x3*vecFragmentNormal);
46+
}
47+
48+
float flLight = 1;
49+
if (bLighted)
50+
{
51+
// Dot product of the sunlight vector and the normal vector of this surface.
52+
// http://youtu.be/0zmLe4SssJc
53+
float flLightDot = dot(-vecSunlight, vecGlobalNormal);
54+
55+
// If the surface normal is > 90 degrees away from the light then clamp the light value to 0.
56+
if (flLightDot < 0)
57+
flLightDot = 0;
58+
59+
// Remap the light values so that they are a little softer
60+
flLight = RemapVal(flLightDot, 1.0, 0.0, 0.9, 0.2);
61+
}
3262

3363
// Multiply that by the color to make a shadow
3464
vec4 vecDiffuse = vecColor * flLight;

content/shaders/pass.vs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@ uniform vec4 vecColor;
22

33
in vec3 vecPosition;
44
in vec3 vecNormal;
5+
in vec3 vecTangent;
6+
in vec3 vecBitangent;
57
in vec2 vecTexCoord0;
68
in vec3 vecVertexColor;
79

810
out vec3 vecFragmentPosition;
911
out vec3 vecFragmentNormal;
12+
out vec3 vecFragmentTangent;
13+
out vec3 vecFragmentBitangent;
1014
out vec2 vecFragmentTexCoord0;
1115
out vec3 vecFragmentColor;
1216

@@ -16,6 +20,8 @@ void main()
1620

1721
vecFragmentPosition = vecPosition;
1822
vecFragmentNormal = vecNormal;
23+
vecFragmentTangent = vecTangent;
24+
vecFragmentBitangent = vecBitangent;
1925
vecFragmentTexCoord0 = vec2(vecTexCoord0.x, 1-vecTexCoord0.y);
2026
vecFragmentColor = vecVertexColor;
2127
}

game/game.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ void CGame::Load()
4343
{
4444
m_iMonsterTexture = GetRenderer()->LoadTextureIntoGL("monster.png");
4545
m_iCrateTexture = GetRenderer()->LoadTextureIntoGL("crate.png");
46+
m_iNormalTexture = GetRenderer()->LoadTextureIntoGL("normal.png");
4647
}
4748

4849
void CGame::MakePuff(const Point& p)
@@ -342,18 +343,30 @@ void CGame::Draw()
342343

343344
r.SetUniform("vecSunlight", vecSunlight);
344345

346+
r.SetUniform("bLighted", true);
345347
r.SetUniform("bDiffuse", false);
346348

347349
// Render the ground.
348350
r.SetUniform("vecColor", Vector4D(0.6f, 0.7f, 0.9f, 1));
351+
r.SetUniform("bNormal", true);
352+
r.SetUniform("iNormal", 1);
353+
r.BindTexture(m_iNormalTexture, 1);
349354
r.BeginRenderTriFan();
350355
r.Normal(Vector(0, 1, 0));
356+
r.Tangent(Vector(1, 0, 0));
357+
r.Bitangent(Vector(0, 0, 1));
358+
r.TexCoord(Vector2D(0, 1));
351359
r.Vertex(Vector(-30, 0, -30));
360+
r.TexCoord(Vector2D(0, 0));
352361
r.Vertex(Vector(-30, 0, 30));
362+
r.TexCoord(Vector2D(1, 0));
353363
r.Vertex(Vector(30, 0, 30));
364+
r.TexCoord(Vector2D(1, 1));
354365
r.Vertex(Vector(30, 0, -30));
355366
r.EndRender();
356367

368+
r.SetUniform("bNormal", false);
369+
357370
{
358371
CRenderingContext r(pRenderer, true);
359372

game/game.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class CGame : public CApplication
9898

9999
size_t m_iMonsterTexture;
100100
size_t m_iCrateTexture;
101+
size_t m_iNormalTexture;
101102

102103
CCharacter* m_apEntityList[MAX_CHARACTERS];
103104
std::vector<CCharacter*> m_apRenderOpaqueList;

renderer/renderingcontext.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ using namespace std;
3232
vector<Vector2D> CRenderingContext::s_avecTexCoord;
3333
vector<vector<Vector2D> > CRenderingContext::s_aavecTexCoords;
3434
vector<Vector> CRenderingContext::s_avecNormals;
35+
vector<Vector> CRenderingContext::s_avecTangents;
36+
vector<Vector> CRenderingContext::s_avecBitangents;
3537
vector<Vector> CRenderingContext::s_avecVertices;
3638

3739
vector<CRenderingContext::CRenderContext> CRenderingContext::s_aContexts;
@@ -558,6 +560,7 @@ void CRenderingContext::BeginRenderTris()
558560

559561
m_bTexCoord = false;
560562
m_bNormal = false;
563+
m_bTangents = false;
561564

562565
m_iDrawMode = GL_TRIANGLES;
563566
}
@@ -572,6 +575,7 @@ void CRenderingContext::BeginRenderTriFan()
572575

573576
m_bTexCoord = false;
574577
m_bNormal = false;
578+
m_bTangents = false;
575579

576580
m_iDrawMode = GL_TRIANGLE_FAN;
577581
}
@@ -586,6 +590,7 @@ void CRenderingContext::BeginRenderTriStrip()
586590

587591
m_bTexCoord = false;
588592
m_bNormal = false;
593+
m_bTangents = false;
589594

590595
m_iDrawMode = GL_TRIANGLE_STRIP;
591596
}
@@ -600,6 +605,7 @@ void CRenderingContext::BeginRenderLines()
600605

601606
m_bTexCoord = false;
602607
m_bNormal = false;
608+
m_bTangents = false;
603609

604610
m_iDrawMode = GL_LINES;
605611
}
@@ -614,6 +620,7 @@ void CRenderingContext::BeginRenderLineLoop()
614620

615621
m_bTexCoord = false;
616622
m_bNormal = false;
623+
m_bTangents = false;
617624

618625
m_iDrawMode = GL_LINE_LOOP;
619626
}
@@ -628,6 +635,7 @@ void CRenderingContext::BeginRenderLineStrip()
628635

629636
m_bTexCoord = false;
630637
m_bNormal = false;
638+
m_bTangents = false;
631639

632640
m_iDrawMode = GL_LINE_STRIP;
633641
}
@@ -647,6 +655,7 @@ void CRenderingContext::BeginRenderPoints(float flSize)
647655

648656
m_bTexCoord = false;
649657
m_bNormal = false;
658+
m_bTangents = false;
650659

651660
glPointSize( flSize );
652661
m_iDrawMode = GL_POINTS;
@@ -685,6 +694,20 @@ void CRenderingContext::Normal(const Vector& v)
685694
m_bNormal = true;
686695
}
687696

697+
void CRenderingContext::Tangent(const Vector& v)
698+
{
699+
TAssert(m_bNormal);
700+
m_vecTangent = v;
701+
m_bTangents = true;
702+
}
703+
704+
void CRenderingContext::Bitangent(const Vector& v)
705+
{
706+
TAssert(m_bNormal);
707+
m_vecBitangent = v;
708+
m_bTangents = true;
709+
}
710+
688711
void CRenderingContext::Vertex(const Vector& v)
689712
{
690713
if (m_bTexCoord)
@@ -699,6 +722,12 @@ void CRenderingContext::Vertex(const Vector& v)
699722
if (m_bNormal)
700723
s_avecNormals.push_back(m_vecNormal);
701724

725+
if (m_bTangents)
726+
{
727+
s_avecTangents.push_back(m_vecTangent);
728+
s_avecBitangents.push_back(m_vecBitangent);
729+
}
730+
702731
s_avecVertices.push_back(v);
703732
}
704733

@@ -742,6 +771,15 @@ void CRenderingContext::EndRender()
742771
glVertexAttribPointer(m_pShader->m_iNormalAttribute, 3, GL_FLOAT, false, 0, s_avecNormals.data());
743772
}
744773

774+
if (m_bTangents && m_pShader->m_iTangentAttribute != ~0 && m_pShader->m_iBitangentAttribute != ~0)
775+
{
776+
glEnableVertexAttribArray(m_pShader->m_iTangentAttribute);
777+
glVertexAttribPointer(m_pShader->m_iTangentAttribute, 3, GL_FLOAT, false, 0, s_avecTangents.data());
778+
779+
glEnableVertexAttribArray(m_pShader->m_iBitangentAttribute);
780+
glVertexAttribPointer(m_pShader->m_iBitangentAttribute, 3, GL_FLOAT, false, 0, s_avecBitangents.data());
781+
}
782+
745783
glEnableVertexAttribArray(m_pShader->m_iPositionAttribute);
746784
glVertexAttribPointer(m_pShader->m_iPositionAttribute, 3, GL_FLOAT, false, 0, s_avecVertices.data());
747785

@@ -755,6 +793,10 @@ void CRenderingContext::EndRender()
755793
}
756794
if (m_pShader->m_iNormalAttribute != ~0)
757795
glDisableVertexAttribArray(m_pShader->m_iNormalAttribute);
796+
if (m_pShader->m_iTangentAttribute != ~0)
797+
glDisableVertexAttribArray(m_pShader->m_iTangentAttribute);
798+
if (m_pShader->m_iBitangentAttribute != ~0)
799+
glDisableVertexAttribArray(m_pShader->m_iBitangentAttribute);
758800
if (m_pShader->m_iColorAttribute != ~0)
759801
glDisableVertexAttribArray(m_pShader->m_iColorAttribute);
760802
}

renderer/renderingcontext.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ class CRenderingContext
134134
void TexCoord(const Vector2D& v, int iChannel = 0);
135135
void TexCoord(const Vector& v, int iChannel = 0);
136136
void Normal(const Vector& v);
137+
void Tangent(const Vector& v);
138+
void Bitangent(const Vector& v);
137139
void Vertex(const Vector& v);
138140
void EndRender();
139141
void CreateVBO(size_t& iVBO, size_t& iVBOSize);
@@ -172,11 +174,19 @@ class CRenderingContext
172174

173175
int m_iDrawMode;
174176
bool m_bTexCoord;
177+
175178
bool m_bNormal;
176179
Vector m_vecNormal;
180+
181+
bool m_bTangents;
182+
Vector m_vecTangent;
183+
Vector m_vecBitangent;
184+
177185
static std::vector<Vector2D> s_avecTexCoord;
178186
static std::vector<std::vector<Vector2D> > s_aavecTexCoords; // A vector of a vector of vectors. Inception!
179187
static std::vector<Vector> s_avecNormals;
188+
static std::vector<Vector> s_avecTangents;
189+
static std::vector<Vector> s_avecBitangents;
180190
static std::vector<Vector> s_avecVertices;
181191

182192
static std::vector<CRenderContext> s_aContexts;

0 commit comments

Comments
 (0)