Added gamma correction, Blinn-Phong shading, and normal map support

This commit is contained in:
Grayson Riffe (Laptop) 2021-09-16 14:05:42 -05:00
parent e7cd6d8132
commit 6daa9d8d25
13 changed files with 101 additions and 25 deletions

View File

@ -4,17 +4,17 @@ void MainState::onEnter() {
Log("MainState onEnter!"); Log("MainState onEnter!");
camera->setType(nf::Camera::Type::FIRST_PERSON); camera->setType(nf::Camera::Type::FIRST_PERSON);
ap.load("example.nfpack"); ap.load("example.nfpack");
test.create(ap["spec.obj"]); test.create(ap["normal.obj"]);
test.setPosition(0.0, 0.0, -5.0); test.setPosition(0.0, 0.05, -5.0);
plane.create(nf::BaseAssets::plane); plane.create(nf::BaseAssets::cube);
plane.setPosition(0.0, -2.0, 0.0); plane.setPosition(0.0, -1.0, 0.0);
plane.setScale(10.0); plane.setScale(50.0, 0.05, 50.0);
text.create("This is a test text.", nf::Vec2(0.1, 0.025), nf::Vec3(0.8)); text.create("This is a test text.", nf::Vec2(0.1, 0.025), nf::Vec3(0.8));
text.centered(true); text.centered(true);
uiTex.create(nf::BaseAssets::logo, nf::Vec2(0.025, 0.025), 0.5); uiTex.create(nf::BaseAssets::logo, nf::Vec2(0.025, 0.025), 0.5);
button.create(nf::Vec2(0.8, 0.025), "Reset"); button.create(nf::Vec2(0.8, 0.025), "Reset");
button2.create(nf::Vec2(0.6, 0.025), "Play Sound"); button2.create(nf::Vec2(0.6, 0.025), "Play Sound");
light.create(nf::Vec3(-5.0, 10.0, 5.0), nf::Vec3(1.0, 1.0, 1.0), 1.0); light.create(nf::Vec3(-5.0, 10.0, 5.0), nf::Vec3(1.0, 1.0, 1.0));
cm.create(nf::BaseAssets::cubemap); cm.create(nf::BaseAssets::cubemap);
sound.create(ap["sound.wav"]); sound.create(ap["sound.wav"]);
@ -51,7 +51,7 @@ void MainState::update(double deltaTime) {
xrot += offset; xrot += offset;
if (app->isKeyHeld(NFI_RIGHT)) if (app->isKeyHeld(NFI_RIGHT))
xrot -= offset; xrot -= offset;
test.setPosition(-xrot / 10.0, 0.0, -yrot / 10.0 - 5.0); light.setPosition(nf::Vec3(-5.0, yrot / 10.0 + 10.0, 5.0));
text.setText("FPS: " + std::to_string(app->getFPS())); text.setText("FPS: " + std::to_string(app->getFPS()));

View File

@ -16,6 +16,8 @@ struct Material {
bool hasSpecTex; bool hasSpecTex;
sampler2D specularTexture; sampler2D specularTexture;
float specPower; float specPower;
bool hasNormTex;
sampler2D normalTexture;
}; };
struct Light { struct Light {
@ -96,6 +98,15 @@ void main() {
if (material.hasSpecTex) if (material.hasSpecTex)
matSpec = texture(material.specularTexture, texCoord).rgb; matSpec = texture(material.specularTexture, texCoord).rgb;
vec3 norm;
if (material.hasNormTex) {
norm = texture(material.normalTexture, texCoord).rgb;
norm = normalize(norm * 2.0 - 1.0);
}
else {
norm = normalize(normals);
}
float ambientStrength = 0.2f; float ambientStrength = 0.2f;
vec3 ambient = ambientStrength * matDiff; vec3 ambient = ambientStrength * matDiff;
if (!isContinued) if (!isContinued)
@ -104,7 +115,6 @@ void main() {
if (light[i].type == 1) { if (light[i].type == 1) {
vec3 lightDir = normalize(light[i].pos - fragPos); vec3 lightDir = normalize(light[i].pos - fragPos);
vec3 norm = normalize(normals);
float diff = max(dot(norm, lightDir), 0.0); float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light[i].color * diff * matDiff * (light[i].strength / 2.0f); vec3 diffuse = light[i].color * diff * matDiff * (light[i].strength / 2.0f);
@ -119,13 +129,12 @@ void main() {
} }
if (light[i].type == 2) { if (light[i].type == 2) {
vec3 lightDir = normalize(light[i].pos - fragPos); vec3 lightDir = normalize(light[i].pos - fragPos);
vec3 norm = normalize(normals);
float diff = max(dot(norm, lightDir), 0.0); float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light[i].color * diff * matDiff * light[i].strength; vec3 diffuse = light[i].color * diff * matDiff * light[i].strength;
vec3 viewDir = normalize(camera.pos - fragPos); vec3 viewDir = normalize(camera.pos - fragPos);
vec3 reflectDir = reflect(-lightDir, norm); vec3 halfway = normalize(lightDir + viewDir);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.specPower); float spec = pow(max(dot(norm, halfway), 0.0), material.specPower);
vec3 specular = light[i].color * spec * matSpec * (light[i].strength / 2.5f); vec3 specular = light[i].color * spec * matSpec * (light[i].strength / 2.5f);
float length = length(light[i].pos - fragPos); float length = length(light[i].pos - fragPos);
@ -136,5 +145,8 @@ void main() {
continue; continue;
} }
} }
//TODO: Move this to a post-processing pass
float gamma = 2.2;
color.rgb = pow(color.rgb, vec3(1.0 / gamma));
outColor = vec4(color, 1.0); outColor = vec4(color, 1.0);
} }

View File

@ -5,10 +5,13 @@ in vec2 texCoord;
uniform sampler2D tex; uniform sampler2D tex;
uniform float opacity; uniform float opacity;
out vec4 color; out vec4 outColor;
void main() { void main() {
vec4 texColor = texture(tex, texCoord); vec4 texColor = texture(tex, texCoord);
vec4 color = texColor;
color = vec4(texColor.rgb, texColor.a * opacity); //TODO: Move this to a post-processing pass too
float gamma = 2.2;
color.rgb = pow(color.rgb, vec3(1.0 / gamma));
outColor = vec4(color.rgb, texColor.a * opacity);
} }

View File

@ -0,0 +1,14 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl mat
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Bump brickwall_normal.jpg
map_Kd brickwall.jpg

View File

@ -0,0 +1,17 @@
# Blender v2.93.3 OBJ File: ''
# www.blender.org
mtllib normal.mtl
o Plane_Plane.001
v -1.000000 -1.000000 -0.000000
v 1.000000 -1.000000 -0.000000
v -1.000000 1.000000 0.000000
v 1.000000 1.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
vn 0.0000 -0.0000 1.0000
usemtl mat
s off
f 2/1/1 3/2/1 1/3/1
f 2/1/1 4/4/1 3/2/1

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 KiB

View File

@ -69,7 +69,10 @@ void getNeededImages(std::string mtl, std::set<std::string>& set) {
unsigned int pos = mtl.find("map_"); unsigned int pos = mtl.find("map_");
if (pos == std::string::npos) if (pos == std::string::npos)
break; break;
mtl = mtl.substr(pos + 7); if (pos == mtl.find("map_Kd") || pos == mtl.find("map_Ks"))
mtl = mtl.substr(pos + 7);
else
mtl = mtl.substr(pos + 9);
std::stringstream ss(mtl); std::stringstream ss(mtl);
std::string temp; std::string temp;
ss >> temp; ss >> temp;
@ -140,7 +143,7 @@ int main(int argc, char* argv[]) {
getNeededImages(mtlContents, neededImages); getNeededImages(mtlContents, neededImages);
if (!neededImages.empty()) { if (!neededImages.empty()) {
currFileContents.insert(0, "\n"); currFileContents.insert(0, "\n");
for(std::string curr : neededImages) { for (std::string curr : neededImages) {
currFileContents.insert(0, curr); currFileContents.insert(0, curr);
currFileContents.insert(0, " "); currFileContents.insert(0, " ");
} }

View File

@ -10,7 +10,7 @@
#include "Utility.h" #include "Utility.h"
namespace nf { namespace nf {
Material::Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess) { Material::Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess, ATexture* normalTex) {
m_vao = new VertexArray(); m_vao = new VertexArray();
m_vao->addBuffer(vb, vbSize); m_vao->addBuffer(vb, vbSize);
m_vao->push<float>(3); m_vao->push<float>(3);
@ -35,9 +35,16 @@ namespace nf {
if (specTex->alreadyLoaded) if (specTex->alreadyLoaded)
m_specularTexture = specTex->loadedTexture; m_specularTexture = specTex->loadedTexture;
else else
m_specularTexture = new Texture(specTex); m_specularTexture = new Texture(specTex, true);
} }
m_shininess = shininess; m_shininess = shininess;
if (normalTex) {
m_hasNormal = true;
if (normalTex->alreadyLoaded)
m_normalTexture = normalTex->loadedTexture;
else
m_normalTexture = new Texture(normalTex, true);
}
} }
void Material::render(Shader* shader, bool onlyDepth) { void Material::render(Shader* shader, bool onlyDepth) {
@ -60,6 +67,13 @@ namespace nf {
} }
else else
shader->setUniform("material.hasSpecTex", false); shader->setUniform("material.hasSpecTex", false);
if (m_hasNormal) {
shader->setUniform("material.hasNormTex", true);
m_normalTexture->bind(2);
shader->setUniform("material.normalTexture", 2);
}
else
shader->setUniform("material.hasNormTex", false);
shader->setUniform("material.specPower", m_shininess); shader->setUniform("material.specPower", m_shininess);
} }
glDrawElements(GL_TRIANGLES, m_ib->getCount(), GL_UNSIGNED_INT, nullptr); glDrawElements(GL_TRIANGLES, m_ib->getCount(), GL_UNSIGNED_INT, nullptr);
@ -94,6 +108,7 @@ namespace nf {
std::string diffuseTextureName; std::string diffuseTextureName;
Vec3 diffuseColor; Vec3 diffuseColor;
std::string specularTextureName; std::string specularTextureName;
std::string normalTextureName;
float shininess = 1.0f; float shininess = 1.0f;
}; };
std::unordered_map<std::string, TempMaterial*> mats; std::unordered_map<std::string, TempMaterial*> mats;
@ -124,6 +139,11 @@ namespace nf {
sscanf_s(mtl.c_str(), "\nmap_Ks %s\n", texName, (unsigned)_countof(texName)); sscanf_s(mtl.c_str(), "\nmap_Ks %s\n", texName, (unsigned)_countof(texName));
mats[currMat]->specularTextureName = (std::string)texName; mats[currMat]->specularTextureName = (std::string)texName;
} }
else if (std::strcmp(line, "map_Bump") == 0) {
char texName[100];
sscanf_s(mtl.c_str(), "\nmap_Bump %s\n", texName, (unsigned)_countof(texName));
mats[currMat]->normalTextureName = (std::string)texName;
}
else if (std::strcmp(line, "Ns") == 0) { else if (std::strcmp(line, "Ns") == 0) {
float s = 0.0; float s = 0.0;
sscanf_s(mtl.c_str(), "\nNs %f\n", &s); sscanf_s(mtl.c_str(), "\nNs %f\n", &s);
@ -277,7 +297,10 @@ namespace nf {
ATexture* spec = nullptr; ATexture* spec = nullptr;
if (curr.specularTextureName.size()) if (curr.specularTextureName.size())
spec = model->neededTextures[curr.specularTextureName]; spec = model->neededTextures[curr.specularTextureName];
m_materials.push_back(new Material(&curr.outVB[0], curr.outVB.size() * sizeof(float), &curr.outTC[0], curr.outTC.size() * sizeof(float), &curr.outVN[0], curr.outVN.size() * sizeof(float), &curr.outIB[0], curr.ibCount, diff, curr.diffuseColor, spec, curr.shininess)); ATexture* norm = nullptr;
if (curr.normalTextureName.size())
norm = model->neededTextures[curr.normalTextureName];
m_materials.push_back(new Material(&curr.outVB[0], curr.outVB.size() * sizeof(float), &curr.outTC[0], curr.outTC.size() * sizeof(float), &curr.outVN[0], curr.outVN.size() * sizeof(float), &curr.outIB[0], curr.ibCount, diff, curr.diffuseColor, spec, curr.shininess, norm));
delete m.second; delete m.second;
} }

View File

@ -387,7 +387,7 @@ namespace nf {
} }
void Renderer::createShadowMap() { void Renderer::createShadowMap() {
m_texSlots = 16; m_texSlots = 13;
glGenFramebuffers(1, &m_shadowMapFBO); glGenFramebuffers(1, &m_shadowMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, m_shadowMapFBO); glBindFramebuffer(GL_FRAMEBUFFER, m_shadowMapFBO);
for (unsigned int i = 0; i < m_texSlots; i++) { for (unsigned int i = 0; i < m_texSlots; i++) {

View File

@ -8,7 +8,7 @@
#include "Utility.h" #include "Utility.h"
namespace nf { namespace nf {
Texture::Texture(ATexture* tex) : Texture::Texture(ATexture* tex, bool linear) :
m_isBase(false), m_isBase(false),
m_id(0), m_id(0),
m_x(0), m_x(0),
@ -23,10 +23,12 @@ namespace nf {
glBindTexture(GL_TEXTURE_2D, m_id); glBindTexture(GL_TEXTURE_2D, m_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_x, m_y, 0, nChannels == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, texture); glTexImage2D(GL_TEXTURE_2D, 0, linear ? GL_RGBA : GL_SRGB_ALPHA, m_x, m_y, 0, nChannels == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, texture);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(texture); stbi_image_free(texture);
m_isBase = tex->isBaseAsset; m_isBase = tex->isBaseAsset;
tex->alreadyLoaded = true;
tex->loadedTexture = this;
} }
void Texture::bind(unsigned int slot) { void Texture::bind(unsigned int slot) {

View File

@ -10,7 +10,7 @@ namespace nf {
class Material : public Drawable { class Material : public Drawable {
public: public:
Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess); Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess, ATexture* normalTex);
void render(Shader* shader, bool onlyDepth); void render(Shader* shader, bool onlyDepth);
@ -22,6 +22,8 @@ namespace nf {
bool m_hasSpecular = false; bool m_hasSpecular = false;
Texture* m_specularTexture = nullptr; Texture* m_specularTexture = nullptr;
float m_shininess; float m_shininess;
bool m_hasNormal = false;
Texture* m_normalTexture = nullptr;
}; };
class Model { class Model {

View File

@ -6,7 +6,7 @@ namespace nf {
class Texture { class Texture {
public: public:
Texture(ATexture* tex); Texture(ATexture* tex, bool linear = false);
void bind(unsigned int slot = 0); void bind(unsigned int slot = 0);
Vec2 getDimensions(); Vec2 getDimensions();