Added geometry shader to pipeline so I can calculate normal data on the GPU
This commit is contained in:
parent
532382b1f9
commit
5b1aba34df
6 changed files with 122 additions and 44 deletions
33
data/shaders/geometry.glsl
Normal file
33
data/shaders/geometry.glsl
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#version 330 core
|
||||||
|
layout (triangles) in;
|
||||||
|
layout (triangle_strip) out;
|
||||||
|
|
||||||
|
in vec2 gtexCoord[];
|
||||||
|
in vec3 gnormCoord[];
|
||||||
|
in vec3 gWorldPos[];
|
||||||
|
|
||||||
|
out vec2 texCoord;
|
||||||
|
out vec3 normCoord;
|
||||||
|
out vec3 WorldPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = gl_in[0].gl_Position;
|
||||||
|
texCoord = gtexCoord[0];
|
||||||
|
normCoord = gnormCoord[0];
|
||||||
|
WorldPos = gWorldPos[0];
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
gl_Position = gl_in[1].gl_Position;
|
||||||
|
texCoord = gtexCoord[1];
|
||||||
|
normCoord = gnormCoord[1];
|
||||||
|
WorldPos = gWorldPos[1];
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
gl_Position = gl_in[2].gl_Position;
|
||||||
|
texCoord = gtexCoord[2];
|
||||||
|
normCoord = gnormCoord[2];
|
||||||
|
WorldPos = gWorldPos[2];
|
||||||
|
EmitVertex();
|
||||||
|
EndPrimitive();
|
||||||
|
};
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#version 330 core
|
#version 330 core
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
||||||
in vec2 ourTexCoord;
|
in vec2 texCoord;
|
||||||
in vec3 ourNormCoord;
|
in vec3 normCoord;
|
||||||
in vec3 WorldPos;
|
in vec3 WorldPos;
|
||||||
in mat4 TBN;
|
//in mat4 TBN;
|
||||||
|
|
||||||
// TODO: make temporary hard coded world/camera pos dynamic
|
// TODO: make temporary hard coded world/camera pos dynamic
|
||||||
//uniform vec3 WorldPos ;
|
//uniform vec3 WorldPos ;
|
||||||
|
|
@ -34,48 +34,48 @@ const float PI = 3.14159265359;
|
||||||
|
|
||||||
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||||
{
|
{
|
||||||
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
|
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||||
{
|
{
|
||||||
float a = roughness*roughness;
|
float a = roughness*roughness;
|
||||||
float a2 = a*a;
|
float a2 = a*a;
|
||||||
float NdotH = max(dot(N, H), 0.0);
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
float NdotH2 = NdotH*NdotH;
|
float NdotH2 = NdotH*NdotH;
|
||||||
|
|
||||||
float num = a2;
|
float num = a2;
|
||||||
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||||
denom = PI * denom * denom;
|
denom = PI * denom * denom;
|
||||||
|
|
||||||
return num / denom;
|
return num / denom;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
{
|
{
|
||||||
float r = (roughness + 1.0);
|
float r = (roughness + 1.0);
|
||||||
float k = (r*r) / 8.0;
|
float k = (r*r) / 8.0;
|
||||||
|
|
||||||
float num = NdotV;
|
float num = NdotV;
|
||||||
float denom = NdotV * (1.0 - k) + k;
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
return num / denom;
|
return num / denom;
|
||||||
}
|
}
|
||||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||||
{
|
{
|
||||||
float NdotV = max(dot(N, V), 0.0);
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
float NdotL = max(dot(N, L), 0.0);
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
return ggx1 * ggx2;
|
return ggx1 * ggx2;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 normal(){
|
vec3 normal(){
|
||||||
// load and invert normal
|
// load and invert normal
|
||||||
vec3 normal = normalize(texture(texture_normal1, ourTexCoord).rgb * 2.0 - 1.0);
|
vec3 normal = normalize(texture(texture_normal1, texCoord).rgb * 2.0 - 1.0);
|
||||||
|
|
||||||
normal = (TBN * vec4(normal, 1.0)).xyz;
|
//normal = (TBN * vec4(normal, 1.0)).xyz;
|
||||||
|
|
||||||
//TODO: Make the normal vector match the matrix of the rest of the model by
|
//TODO: Make the normal vector match the matrix of the rest of the model by
|
||||||
//actually calculating the TBN
|
//actually calculating the TBN
|
||||||
|
|
@ -92,7 +92,7 @@ vec3 PBR(vec3 albedo, float roughness, float metallic, float ao)
|
||||||
//vec3 lightColor = vec3(1.0, 1.0, 1.0) - sin(tick / 90);
|
//vec3 lightColor = vec3(1.0, 1.0, 1.0) - sin(tick / 90);
|
||||||
vec3 lightColor = vec3(13.47, 11.31, 10.79);
|
vec3 lightColor = vec3(13.47, 11.31, 10.79);
|
||||||
|
|
||||||
vec3 N = normalize(ourNormCoord);
|
vec3 N = normalize(normCoord);
|
||||||
vec3 V = normalize(CameraPos - WorldPos);
|
vec3 V = normalize(CameraPos - WorldPos);
|
||||||
N = (N + normal()) / 2;
|
N = (N + normal()) / 2;
|
||||||
//N = normal(); For seeing if normal map tracks with light.
|
//N = normal(); For seeing if normal map tracks with light.
|
||||||
|
|
@ -136,12 +136,12 @@ vec3 PBR(vec3 albedo, float roughness, float metallic, float ao)
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 albedo;
|
vec3 albedo;
|
||||||
albedo.r = pow(texture(texture_diffuse1, ourTexCoord).r, 2.2);
|
albedo.r = pow(texture(texture_diffuse1, texCoord).r, 2.2);
|
||||||
albedo.g = pow(texture(texture_diffuse1, ourTexCoord).g, 2.2);
|
albedo.g = pow(texture(texture_diffuse1, texCoord).g, 2.2);
|
||||||
albedo.b = pow(texture(texture_diffuse1, ourTexCoord).b, 2.2);
|
albedo.b = pow(texture(texture_diffuse1, texCoord).b, 2.2);
|
||||||
float roughness = texture(texture_rma1, ourTexCoord).r;
|
float roughness = texture(texture_rma1, texCoord).r;
|
||||||
float metallic = texture(texture_rma1, ourTexCoord).g;
|
float metallic = texture(texture_rma1, texCoord).g;
|
||||||
float ao = texture(texture_rma1, ourTexCoord).b;
|
float ao = texture(texture_rma1, texCoord).b;
|
||||||
|
|
||||||
FragColor = vec4(PBR(albedo, roughness, metallic, ao), 1.0);
|
FragColor = vec4(PBR(albedo, roughness, metallic, ao), 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,23 +6,20 @@ layout (location = 2) in vec2 aTexCoord;
|
||||||
uniform mat4 MVP;
|
uniform mat4 MVP;
|
||||||
uniform mat4 Model;
|
uniform mat4 Model;
|
||||||
|
|
||||||
out vec2 ourTexCoord;
|
out vec2 gtexCoord;
|
||||||
out vec3 ourNormCoord;
|
out vec3 gnormCoord;
|
||||||
|
|
||||||
//Pbr
|
//Pbr
|
||||||
out vec3 WorldPos;
|
out vec3 gWorldPos;
|
||||||
|
|
||||||
//Normals
|
//Normals
|
||||||
out mat4 TBN;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = MVP * Model * vec4(aPos, 1.0);
|
gl_Position = MVP * Model * vec4(aPos, 1.0);
|
||||||
ourNormCoord = aNormal;
|
gnormCoord = aNormal;
|
||||||
ourTexCoord = aTexCoord;
|
gtexCoord = aTexCoord;
|
||||||
|
|
||||||
TBN = Model;
|
|
||||||
|
|
||||||
// Calculate position of fragment
|
// Calculate position of fragment
|
||||||
WorldPos = vec3(Model * vec4(aPos, 1.0));
|
gWorldPos = vec3(Model * vec4(aPos, 1.0));
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,54 @@
|
||||||
#include "ShaderLoader.h"
|
#include "ShaderLoader.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
ShaderLoader::ShaderLoader(const char *vertexPath, const char *fragmentPath) {
|
// This function always expects vertex and fragment shaders, if a geometry
|
||||||
|
// shader is present then it will also compile in that boi too.
|
||||||
|
// TODO: Make this code more readable and reduce the number of if statements.
|
||||||
|
void ShaderLoader::loadShader(const char *vertexPath, const char *fragmentPath,
|
||||||
|
const char *geometryPath) {
|
||||||
std::string vertexCode;
|
std::string vertexCode;
|
||||||
std::string fragmentCode;
|
std::string fragmentCode;
|
||||||
|
std::string geometryCode;
|
||||||
|
|
||||||
std::ifstream vShaderFile;
|
std::ifstream vShaderFile;
|
||||||
std::ifstream fShaderFile;
|
std::ifstream fShaderFile;
|
||||||
|
std::ifstream gShaderFile;
|
||||||
|
|
||||||
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||||
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||||
|
if (geometryPath != nullptr)
|
||||||
|
gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||||
try {
|
try {
|
||||||
// Open Files
|
// Open Files
|
||||||
vShaderFile.open(vertexPath);
|
vShaderFile.open(vertexPath);
|
||||||
fShaderFile.open(fragmentPath);
|
fShaderFile.open(fragmentPath);
|
||||||
std::stringstream vShaderStream, fShaderStream;
|
if (geometryPath != nullptr)
|
||||||
|
gShaderFile.open(geometryPath);
|
||||||
|
std::stringstream vShaderStream, fShaderStream, gShaderStream;
|
||||||
// read file's buffer contents into streams
|
// read file's buffer contents into streams
|
||||||
vShaderStream << vShaderFile.rdbuf();
|
vShaderStream << vShaderFile.rdbuf();
|
||||||
fShaderStream << fShaderFile.rdbuf();
|
fShaderStream << fShaderFile.rdbuf();
|
||||||
|
if (geometryPath != nullptr)
|
||||||
|
gShaderStream << gShaderFile.rdbuf();
|
||||||
// close file handlers
|
// close file handlers
|
||||||
vShaderFile.close();
|
vShaderFile.close();
|
||||||
fShaderFile.close();
|
fShaderFile.close();
|
||||||
|
if (geometryPath != nullptr)
|
||||||
|
gShaderFile.close();
|
||||||
// convert stream into string
|
// convert stream into string
|
||||||
vertexCode = vShaderStream.str();
|
vertexCode = vShaderStream.str();
|
||||||
fragmentCode = fShaderStream.str();
|
fragmentCode = fShaderStream.str();
|
||||||
|
if (geometryPath != nullptr)
|
||||||
|
geometryCode = gShaderStream.str();
|
||||||
} catch (std::string e) {
|
} catch (std::string e) {
|
||||||
error.crash("Failed to read shaderfiles", e);
|
error.crash("Failed to read shaderfiles", e);
|
||||||
}
|
}
|
||||||
const char *vShaderCode = vertexCode.c_str();
|
const char *vShaderCode = vertexCode.c_str();
|
||||||
const char *fShaderCode = fragmentCode.c_str();
|
const char *fShaderCode = fragmentCode.c_str();
|
||||||
|
const char *gShaderCode = geometryCode.c_str();
|
||||||
|
|
||||||
// Compile shaders
|
// Compile shaders
|
||||||
unsigned int vertex, fragment;
|
unsigned int vertex, fragment, geometry;
|
||||||
int success;
|
int success;
|
||||||
char infoLog[512];
|
char infoLog[512];
|
||||||
|
|
||||||
|
|
@ -60,10 +77,25 @@ ShaderLoader::ShaderLoader(const char *vertexPath, const char *fragmentPath) {
|
||||||
error.crash("Fragment shader compilation failed", infoLog);
|
error.crash("Fragment shader compilation failed", infoLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create geometry shader
|
||||||
|
if (geometryPath != nullptr) {
|
||||||
|
geometry = glCreateShader(GL_GEOMETRY_SHADER);
|
||||||
|
// compile fragment shader
|
||||||
|
glShaderSource(geometry, 1, &gShaderCode, NULL);
|
||||||
|
glCompileShader(geometry);
|
||||||
|
// https://learnopengl.com/Getting-started/Hello-Triangle
|
||||||
|
glGetShaderiv(geometry, GL_COMPILE_STATUS, &success);
|
||||||
|
if (!success) {
|
||||||
|
glGetShaderInfoLog(geometry, 512, NULL, infoLog);
|
||||||
|
error.crash("Geometry shader compilation failed", infoLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
// shader Program
|
// shader Program
|
||||||
ID = glCreateProgram();
|
ID = glCreateProgram();
|
||||||
glAttachShader(ID, vertex);
|
glAttachShader(ID, vertex);
|
||||||
glAttachShader(ID, fragment);
|
glAttachShader(ID, fragment);
|
||||||
|
if (geometryPath != nullptr)
|
||||||
|
glAttachShader(ID, geometry);
|
||||||
glLinkProgram(ID);
|
glLinkProgram(ID);
|
||||||
// print linking errors if any
|
// print linking errors if any
|
||||||
glGetProgramiv(ID, GL_LINK_STATUS, &success);
|
glGetProgramiv(ID, GL_LINK_STATUS, &success);
|
||||||
|
|
@ -76,6 +108,16 @@ ShaderLoader::ShaderLoader(const char *vertexPath, const char *fragmentPath) {
|
||||||
// necessary
|
// necessary
|
||||||
glDeleteShader(vertex);
|
glDeleteShader(vertex);
|
||||||
glDeleteShader(fragment);
|
glDeleteShader(fragment);
|
||||||
|
glDeleteShader(geometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderLoader::ShaderLoader(const char *vertexPath, const char *fragmentPath,
|
||||||
|
const char *geometryPath) {
|
||||||
|
this->loadShader(vertexPath, fragmentPath, geometryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderLoader::ShaderLoader(const char *vertexPath, const char *fragmentPath) {
|
||||||
|
this->loadShader(vertexPath, fragmentPath, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderLoader::use() { glUseProgram(ID); }
|
void ShaderLoader::use() { glUseProgram(ID); }
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,14 @@ private:
|
||||||
unsigned int ID;
|
unsigned int ID;
|
||||||
Error error = Error("ShaderLoader");
|
Error error = Error("ShaderLoader");
|
||||||
|
|
||||||
|
void loadShader(const char *vertexPath, const char *fragmentPath,
|
||||||
|
const char *geometryPath);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructor builds shader
|
// constructor builds shader
|
||||||
ShaderLoader(const char *vertexPath, const char *fragmentPath);
|
ShaderLoader(const char *vertexPath, const char *fragmentPath);
|
||||||
|
ShaderLoader(const char *vertexPath, const char *fragmentPath,
|
||||||
|
const char *geometryPath);
|
||||||
|
|
||||||
// use the shader
|
// use the shader
|
||||||
void use();
|
void use();
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ int main(int argc, char **argv) {
|
||||||
SDL_Event input;
|
SDL_Event input;
|
||||||
|
|
||||||
ShaderLoader shader(ROOT_DIR "data/shaders/pbrVertex.glsl",
|
ShaderLoader shader(ROOT_DIR "data/shaders/pbrVertex.glsl",
|
||||||
ROOT_DIR "data/shaders/pbrFragment.glsl");
|
ROOT_DIR "data/shaders/pbrFragment.glsl",
|
||||||
|
ROOT_DIR "data/shaders/geometry.glsl");
|
||||||
|
|
||||||
// Model backpack(std::string(ROOT_DIR) +
|
// Model backpack(std::string(ROOT_DIR) +
|
||||||
// std::string("data/models/backpack/backpack.obj"));
|
// std::string("data/models/backpack/backpack.obj"));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue