Skip to content

Commit 80c7a03

Browse files
authored
Closes #5 billboard sprites (#232)
1 parent a20a44f commit 80c7a03

File tree

9 files changed

+281
-18
lines changed

9 files changed

+281
-18
lines changed

app/main3d.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,14 +502,16 @@ int main(int argc, char** argv)
502502
gameRunner.mSystems->GetRenderables(),
503503
light,
504504
lightCamera,
505-
*cameraPtr);
505+
*cameraPtr,
506+
false);
506507

507508
renderer.DrawWithShadow(
508509
gameRunner.GetZoneRenderData(),
509510
gameRunner.mSystems->GetSprites(),
510511
light,
511512
lightCamera,
512-
*cameraPtr);
513+
*cameraPtr,
514+
true);
513515

514516
const auto& dynamicRenderables = gameRunner.mSystems->GetDynamicRenderables();
515517
for (const auto& obj : dynamicRenderables)
@@ -521,7 +523,8 @@ int main(int argc, char** argv)
521523
data,
522524
light,
523525
lightCamera,
524-
*cameraPtr);
526+
*cameraPtr,
527+
true);
525528
}
526529
}
527530

game/gameRunner.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "game/combatModelLoader.hpp"
2525

26+
#include "graphics/glm.hpp"
2627
#include "gui/guiManager.hpp"
2728
#include "gui/IDialogScene.hpp"
2829

@@ -141,11 +142,12 @@ void GameRunner::LoadSystems()
141142
if (item.GetZoneItem().GetVertices().size() > 1)
142143
{
143144
auto id = mSystems->GetNextItemId();
145+
auto rotation = item.GetZoneItem().IsSprite() ? Graphics::sNinetyDegreeRotation : item.GetRotation();
144146
auto renderable = Renderable{
145147
id,
146148
mZoneData->mObjects.GetObject(item.GetZoneItem().GetName()),
147149
item.GetLocation(),
148-
item.GetRotation(),
150+
rotation,
149151
glm::vec3{static_cast<float>(item.GetZoneItem().GetScale())}};
150152

151153
if (item.GetZoneItem().IsSprite())
@@ -329,7 +331,7 @@ void GameRunner::LoadCombatants(std::uint8_t tileIndex)
329331
entityId,
330332
{},
331333
BAK::ToGlCoord<float>(combatant.mLocation.mPosition + tilePos),
332-
glm::vec3{0},
334+
Graphics::sNinetyDegreeRotation,
333335
glm::vec3{1},
334336
BAK::MonsterIndex{combatant.mMonster},
335337
combatComplete ? BAK::AnimationType::Dead : BAK::AnimationType::Idle,

graphics/glm.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,6 @@ bool PointWithinRectangle(glm::vec<2, T> point, glm::vec<2, T> topLeft, glm::vec
3737
&& glm::all(glm::lessThanEqual(point, bottomRight));
3838
}
3939

40+
constexpr auto sNinetyDegreeRotation = glm::vec3{0, glm::pi<float>() * .5, 0};
41+
4042
}

graphics/renderer.hpp

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,24 @@ class Renderer
3535
"directional.frag.glsl"};
3636
return shader.Compile();
3737
})},
38+
mSpriteShader{std::invoke([]{
39+
auto shader = ShaderProgram{
40+
"sprite.vert.glsl",
41+
"sprite.frag.glsl"};
42+
return shader.Compile();
43+
})},
3844
mPickShader{std::invoke([]{
3945
auto shader = ShaderProgram{
4046
"pick.vert.glsl",
4147
"pick.frag.glsl"};
4248
return shader.Compile();
4349
})},
50+
mPickSpriteShader{std::invoke([]{
51+
auto shader = ShaderProgram{
52+
"pick.sprite.vert.glsl",
53+
"pick.sprite.frag.glsl"};
54+
return shader.Compile();
55+
})},
4456
mShadowMapShader{std::invoke([]{
4557
auto shader = ShaderProgram{
4658
"shadowMap.vert.glsl",
@@ -99,18 +111,21 @@ class Renderer
99111
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
100112
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
101113

102-
auto& shader = mPickShader;
103-
shader.UseProgramGL();
114+
auto* shader = &mPickShader;
115+
shader->UseProgramGL();
104116

105-
shader.SetUniform(shader.GetUniformLocation("texture0"), 0);
117+
shader->SetUniform(shader->GetUniformLocation("texture0"), 0);
106118

107-
const auto mvpMatrixId = shader.GetUniformLocation("MVP");
108-
const auto entityIdId = shader.GetUniformLocation("entityId");
119+
auto mvpMatrixId = shader->GetUniformLocation("MVP");
120+
auto entityIdId = shader->GetUniformLocation("entityId");
121+
122+
auto modelMatrixId = mPickSpriteShader.GetUniformLocation("M");
123+
auto cameraPositionId = mPickSpriteShader.GetUniformLocation("cameraPosition_worldspace");
109124

110125
const auto& viewMatrix = camera.GetViewMatrix();
111126
glm::mat4 MVP;
112127

113-
const auto RenderItem = [&](const auto& item)
128+
const auto RenderItem = [&](const auto& item, bool isSprite)
114129
{
115130
if (glm::distance(camera.GetPosition(), item.GetLocation()) > sClickDistance) return;
116131

@@ -119,8 +134,13 @@ class Renderer
119134

120135
MVP = camera.GetProjectionMatrix() * viewMatrix * modelMatrix;
121136

122-
shader.SetUniform(mvpMatrixId, MVP);
123-
shader.SetUniform(entityIdId, item.GetId().mValue);
137+
shader->SetUniform(mvpMatrixId, MVP);
138+
shader->SetUniform(entityIdId, item.GetId().mValue);
139+
if (isSprite)
140+
{
141+
shader->SetUniform(modelMatrixId, modelMatrix);
142+
shader->SetUniform(cameraPositionId, camera.GetPosition());
143+
}
124144

125145
glDrawElementsBaseVertex(
126146
GL_TRIANGLES,
@@ -133,18 +153,26 @@ class Renderer
133153

134154
for (const auto& item : renderables)
135155
{
136-
RenderItem(item);
156+
RenderItem(item, false);
137157
}
138158

159+
shader = &mPickSpriteShader;
160+
shader->UseProgramGL();
161+
162+
shader->SetUniform(shader->GetUniformLocation("texture0"), 0);
163+
164+
mvpMatrixId = shader->GetUniformLocation("MVP");
165+
entityIdId = shader->GetUniformLocation("entityId");
166+
139167
for (const auto& item : sprites)
140168
{
141-
RenderItem(item);
169+
RenderItem(item, true);
142170
}
143171

144172
for (const auto& item : dynamicRenderables)
145173
{
146174
item.GetRenderData()->Bind(GL_TEXTURE0);
147-
RenderItem(item);
175+
RenderItem(item, true);
148176
}
149177

150178
mPickFB.UnbindGL();
@@ -157,7 +185,8 @@ class Renderer
157185
const Renderables& renderables,
158186
const Light& light,
159187
const Camera& lightCamera,
160-
const Camera& camera)
188+
const Camera& camera,
189+
bool isSprite)
161190
{
162191
renderData.Bind(GL_TEXTURE0);
163192

@@ -167,7 +196,7 @@ class Renderer
167196
? mDepthBuffer1.GetId()
168197
: mDepthBuffer2.GetId());
169198

170-
auto& shader = mModelShader;
199+
auto& shader = isSprite ? mSpriteShader : mModelShader;
171200
shader.UseProgramGL();
172201

173202
shader.SetUniform(shader.GetUniformLocation("texture0"), 0);
@@ -301,7 +330,9 @@ class Renderer
301330

302331
//private:
303332
ShaderProgramHandle mModelShader;
333+
ShaderProgramHandle mSpriteShader;
304334
ShaderProgramHandle mPickShader;
335+
ShaderProgramHandle mPickSpriteShader;
305336
ShaderProgramHandle mShadowMapShader;
306337
ShaderProgramHandle mNormalShader;
307338

shaders/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ list(APPEND SHADERS
1414
instance
1515
gui
1616
pick
17+
pick.sprite
18+
sprite
1719
shadowMap
1820
)
1921

shaders/pick.sprite.frag.glsl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#version 330 core
2+
3+
in vec3 uvCoords;
4+
in float texBlend;
5+
6+
// Ouput data
7+
out vec4 color;
8+
9+
uniform sampler2DArray texture0;
10+
uniform uint entityId;
11+
12+
void main()
13+
{
14+
vec4 textureSample = texture(texture0, uvCoords);
15+
float textureAlpha = textureSample.a;
16+
17+
if (!(texBlend < 1) && textureAlpha == 0) discard;
18+
19+
// I want to output this RGBui8 but can't get it working
20+
float entityIdR = (entityId & 0xffu);
21+
float entityIdG = ((entityId >> 8) & 0xffu);
22+
float entityIdB = ((entityId >> 16) & 0xffu);
23+
float entityIdA = ((entityId >> 24) & 0xffu);
24+
color = vec4(entityIdR, entityIdG, entityIdB, entityIdA);
25+
}
26+

shaders/pick.sprite.vert.glsl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#version 330 core
2+
3+
layout(location = 0) in vec3 vertexPosition_modelspace;
4+
layout(location = 1) in vec3 vertexNormal_modelspace;
5+
layout(location = 2) in vec4 vertexColor_modelspace;
6+
layout(location = 3) in vec3 textureCoords;
7+
layout(location = 4) in float texBlendVec;
8+
9+
out vec3 uvCoords;
10+
out float texBlend;
11+
12+
uniform mat4 MVP;
13+
uniform mat4 M;
14+
uniform vec3 cameraPosition_worldspace;
15+
16+
void main(){
17+
vec3 vertexPosition_worldspace = (M * vec4(vertexPosition_modelspace, 1.0)).xyz;
18+
vec3 direction_toCamera = normalize(cameraPosition_worldspace - vertexPosition_worldspace);
19+
mat4 billboardRotationMatrix;
20+
21+
billboardRotationMatrix[0] = vec4(direction_toCamera.x, 0.0, direction_toCamera.z, 0.0);
22+
billboardRotationMatrix[1] = vec4(0.0, 1.0, 0.0, 0.0);
23+
billboardRotationMatrix[2] = vec4(-direction_toCamera.z, 0.0, direction_toCamera.x, 0.0);
24+
billboardRotationMatrix[3] = vec4(0.0, 0.0, 0.0, 1.0);
25+
26+
vec4 billboardPosition = billboardRotationMatrix * vec4(vertexPosition_modelspace, 1.0);
27+
28+
gl_Position = MVP * billboardPosition;
29+
30+
uvCoords = textureCoords.xyz;
31+
texBlend = texBlendVec;
32+
}

shaders/sprite.frag.glsl

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#version 330 core
2+
3+
struct Light
4+
{
5+
vec3 mDirection;
6+
vec3 mAmbientColor;
7+
vec3 mDiffuseColor;
8+
vec3 mSpecularColor;
9+
};
10+
11+
in vec3 Position_lightSpace;
12+
in vec3 Normal_cameraspace;
13+
in vec3 EyeDirection_cameraspace;
14+
in vec3 lightDirection_cameraspace;
15+
16+
in vec4 vertexColor;
17+
in vec3 uvCoords;
18+
in float texBlend;
19+
in float DistanceFromCamera;
20+
21+
// Ouput data
22+
out vec4 color;
23+
24+
uniform vec3 fogColor;
25+
uniform Light light;
26+
uniform sampler2DArray texture0;
27+
uniform sampler2D shadowMap;
28+
uniform mat4 lightSpaceMatrix;
29+
30+
float ShadowCalculation(vec4 fragPosLightSpace)
31+
{
32+
// perform perspective divide
33+
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
34+
// transform to [0,1] range
35+
projCoords = projCoords * 0.5 + 0.5;
36+
// get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
37+
float closestDepth = texture(shadowMap, projCoords.xy).r;
38+
// get depth of current fragment from light's perspective
39+
float currentDepth = projCoords.z;
40+
// check whether current frag pos is in shadow
41+
float shadow = (currentDepth - .001) > closestDepth ? 1.0 : 0.0;
42+
43+
return shadow;
44+
}
45+
46+
void main()
47+
{
48+
float k = .0005;
49+
float fogFactor = exp(-DistanceFromCamera * k);
50+
51+
vec3 materialDiffuseColor = vertexColor.xyz;
52+
float materialAlpha = vertexColor.a;
53+
54+
vec4 textureSample = texture(texture0, uvCoords);
55+
vec3 textureColor = textureSample.xyz;
56+
float textureAlpha = textureSample.a;
57+
58+
// Choose either vertex color or texture color with the texBlend
59+
vec3 diffuseColor = mix(materialDiffuseColor, textureColor, texBlend);
60+
float alpha = mix(materialAlpha, textureAlpha, texBlend);
61+
62+
if (alpha == 0) discard;
63+
64+
vec3 materialAmbientColor = diffuseColor;
65+
vec3 materialSpecularColor = materialDiffuseColor;
66+
67+
// Normal of the computed fragment, in camera space
68+
vec3 n = Normal_cameraspace;
69+
// Direction of the light (from the fragment to the light)
70+
vec3 l = lightDirection_cameraspace;
71+
72+
// Cosine of the angle between the normal and the light direction,
73+
// clamped above 0
74+
// - light is at the vertical of the triangle -> 1
75+
// - light is perpendicular to the triangle -> 0
76+
// - light is behind the triangle -> 0
77+
float cosTheta = clamp(dot(n, l), 0, 1);
78+
79+
// Eye vector (towards the camera)
80+
vec3 E = EyeDirection_cameraspace;
81+
// Direction in which the triangle reflects the light
82+
vec3 R = reflect(-l, n);
83+
// Cosine of the angle between the Eye vector and the Reflect vector,
84+
// clamped to 0
85+
// - Looking into the reflection -> 1
86+
// - Looking elsewhere -> < 1
87+
float cosAlpha = clamp(dot(E, R), 0, 1);
88+
89+
float shadow = ShadowCalculation(vec4(Position_lightSpace, 1));
90+
91+
vec3 litColor
92+
= materialAmbientColor * light.mAmbientColor
93+
+ (1 - shadow)
94+
* (cosTheta * diffuseColor * light.mDiffuseColor
95+
+ pow(cosAlpha, 4) * materialSpecularColor * light.mSpecularColor);
96+
97+
vec3 foggedColor = mix(fogColor, litColor, fogFactor);
98+
99+
color = vec4(foggedColor, alpha);
100+
}
101+

0 commit comments

Comments
 (0)