Merge branch 'feature/7-codebase-refactoring' into 'main'

Update uniform handling

See merge request jack/terravisor!2
This commit is contained in:
Jack Christensen 2024-08-26 03:32:58 +00:00
commit 5d1d56bc5c
10 changed files with 406 additions and 359 deletions

3
CHANGELOG.md Normal file
View File

@ -0,0 +1,3 @@
## [v0.1.1] - 2024-08-25
### Changed
- Refactored uniform handling in the initial geometry pass to improve maintainability.

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(TerraVisor VERSION 0.0.1) project(TerraVisor VERSION 0.0.2)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)

View File

@ -2,6 +2,7 @@
#include <GL/glew.h> #include <GL/glew.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <string>
namespace Uniforms namespace Uniforms
{ {
@ -15,6 +16,17 @@ namespace Uniforms
glm::vec4 eye_w = glm::vec4(0.0f, 0.0f, 3.0f, 1.0f); //world-space eye position glm::vec4 eye_w = glm::vec4(0.0f, 0.0f, 3.0f, 1.0f); //world-space eye position
}; };
struct GeoUniforms
{
glm::mat4 PV;
glm::mat4 M;
float minTessellation = 1.0f;
float maxTessellation = 32.0f;
float displacementScale = 0.007f;
int gridDensity = 16;
};
struct LightUniforms struct LightUniforms
{ {
glm::vec4 La = glm::vec4(0.5f, 0.5f, 0.55f, 1.0f); //ambient light color glm::vec4 La = glm::vec4(0.5f, 0.5f, 0.55f, 1.0f); //ambient light color
@ -34,11 +46,13 @@ namespace Uniforms
extern SceneUniforms SceneData; extern SceneUniforms SceneData;
extern LightUniforms LightData; extern LightUniforms LightData;
extern MaterialUniforms MaterialData; extern MaterialUniforms MaterialData;
extern GeoUniforms GeoData;
//IDs for the buffer objects holding the uniform block data //IDs for the buffer objects holding the uniform block data
extern GLuint scene_ubo; extern GLuint sceneUbo;
extern GLuint light_ubo; extern GLuint lightUbo;
extern GLuint material_ubo; extern GLuint materialUbo;
extern GLuint geoUbo;
namespace UboBinding namespace UboBinding
{ {
@ -46,6 +60,7 @@ namespace Uniforms
extern int scene; extern int scene;
extern int light; extern int light;
extern int material; extern int material;
extern int geo;
}; };
//Locations for the uniforms which are not in uniform blocks //Locations for the uniforms which are not in uniform blocks

View File

@ -9,12 +9,6 @@ in TE_OUT {
vec3 normal; vec3 normal;
} fs_in; } fs_in;
layout(std140, binding = 0) uniform SceneUniforms
{
mat4 PV; //camera projection * view matrix
vec4 eye_w; //world-space eye position
};
layout(location = 0) out vec4 albedoGbuffer; layout(location = 0) out vec4 albedoGbuffer;
layout(location = 1) out vec4 positionGbuffer; layout(location = 1) out vec4 positionGbuffer;
layout(location = 2) out vec4 normalGbuffer; layout(location = 2) out vec4 normalGbuffer;

View File

@ -2,6 +2,20 @@
layout(vertices = 4) out; layout(vertices = 4) out;
layout(binding = 0) uniform sampler2D heightTexture;
uniform float tessellationFactor;
layout(std140, binding = 4) uniform GeoUniforms
{
mat4 PV;
mat4 M;
float minTessellation;
float maxTessellation;
float displacementScale;
int gridDensity;
};
in VS_OUT { in VS_OUT {
vec3 position; vec3 position;
vec2 texCoord; vec2 texCoord;
@ -12,21 +26,19 @@ out TC_OUT {
vec2 texCoord; vec2 texCoord;
} tc_out[]; } tc_out[];
uniform float tessellationFactor;
void main() { void main() {
// Set tessellation levels
if (gl_InvocationID == 0) {
gl_TessLevelOuter[0] = tessellationFactor; // Level of tessellation along one edge
gl_TessLevelOuter[1] = tessellationFactor; // Level of tessellation along another edge
gl_TessLevelOuter[2] = tessellationFactor; // Level of tessellation along the other edge
gl_TessLevelOuter[3] = tessellationFactor; // Level of tessellation along the other edge
gl_TessLevelInner[0] = tessellationFactor; // Level of tessellation for the inner part
gl_TessLevelInner[1] = tessellationFactor; // Level of tessellation for the inner part
}
// Pass through position and texture coordinates to the tessellation evaluation shader // Pass through position and texture coordinates to the tessellation evaluation shader
tc_out[gl_InvocationID].position = tc_in[gl_InvocationID].position; tc_out[gl_InvocationID].position = tc_in[gl_InvocationID].position;
tc_out[gl_InvocationID].texCoord = tc_in[gl_InvocationID].texCoord; tc_out[gl_InvocationID].texCoord = tc_in[gl_InvocationID].texCoord;
// Set tessellation levels
if (gl_InvocationID == 0) {
gl_TessLevelOuter[0] = maxTessellation;
gl_TessLevelOuter[1] = maxTessellation;
gl_TessLevelOuter[2] = maxTessellation;
gl_TessLevelOuter[3] = maxTessellation;
gl_TessLevelInner[0] = maxTessellation;
gl_TessLevelInner[1] = maxTessellation;
}
} }

View File

@ -3,15 +3,16 @@
layout(quads, fractional_even_spacing, cw) in; layout(quads, fractional_even_spacing, cw) in;
layout(binding = 0) uniform sampler2D heightTexture; layout(binding = 0) uniform sampler2D heightTexture;
layout(location = 0) uniform mat4 M;
uniform float displacementScale = 0.025f; layout(std140, binding = 4) uniform GeoUniforms
uniform float tessellationFactor;
layout(std140, binding = 0) uniform SceneUniforms
{ {
mat4 PV; //camera projection * view matrix mat4 PV;
vec4 eye_w; //world-space eye position mat4 M;
float minTessellation;
float maxTessellation;
float displacementScale;
int gridDensity;
}; };
in TC_OUT { in TC_OUT {
@ -30,13 +31,16 @@ float getHeight(vec2 uv) {
} }
vec3 calculateSmoothNormal(vec3 pos, vec2 coord) { vec3 calculateSmoothNormal(vec3 pos, vec2 coord) {
float step = 1.0f / (16.0f * tessellationFactor + 1.0f); // Currently hardcoded to match patch density
float step = 1.0f / (float(gridDensity) * maxTessellation + 1.0f);
// Find surrounding heights
float hLeft = getHeight(coord + vec2(-step, 0.0f)); float hLeft = getHeight(coord + vec2(-step, 0.0f));
float hRight = getHeight(coord + vec2(step, 0.0f)); float hRight = getHeight(coord + vec2(step, 0.0f));
float hUp = getHeight(coord + vec2(0.0f, step)); float hUp = getHeight(coord + vec2(0.0f, step));
float hDown = getHeight(coord + vec2(0.0f, -step)); float hDown = getHeight(coord + vec2(0.0f, -step));
// Calculate tangents
vec3 tangentX = normalize(vec3(step, hRight - hLeft, 0.0)); vec3 tangentX = normalize(vec3(step, hRight - hLeft, 0.0));
vec3 tangentY = normalize(vec3(0.0, hUp - hDown, step)); vec3 tangentY = normalize(vec3(0.0, hUp - hDown, step));

View File

@ -1,7 +1,7 @@
#version 450 core #version 450 core
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 posAttrib;
layout(location = 1) in vec2 inTexCoord; layout(location = 1) in vec2 texCoordAttrib;
out VS_OUT { out VS_OUT {
vec3 position; vec3 position;
@ -9,6 +9,6 @@ out VS_OUT {
} vs_out; } vs_out;
void main() { void main() {
vs_out.position = (vec4(inPosition, 1.0f)).xyz; vs_out.position = (vec4(posAttrib, 1.0f)).xyz;
vs_out.texCoord = inTexCoord; vs_out.texCoord = texCoordAttrib;
} }

View File

@ -10,106 +10,106 @@ using namespace std;
// Create a NULL-terminated string by reading the provided file // Create a NULL-terminated string by reading the provided file
static char* readShaderSource(const char* shaderFile) static char* readShaderSource(const char* shaderFile)
{ {
ifstream ifs(shaderFile, ios::in | ios::binary | ios::ate); ifstream ifs(shaderFile, ios::in | ios::binary | ios::ate);
if (ifs.is_open()) if (ifs.is_open())
{ {
unsigned int filesize = static_cast<unsigned int>(ifs.tellg()); unsigned int filesize = static_cast<unsigned int>(ifs.tellg());
ifs.seekg(0, ios::beg); ifs.seekg(0, ios::beg);
char* bytes = new char[filesize + 1]; char* bytes = new char[filesize + 1];
memset(bytes, 0, filesize + 1); memset(bytes, 0, filesize + 1);
ifs.read(bytes, filesize); ifs.read(bytes, filesize);
ifs.close(); ifs.close();
return bytes; return bytes;
} }
return NULL; return NULL;
} }
void printShaderCompileError(GLuint shader) void printShaderCompileError(GLuint shader)
{ {
GLint logSize; GLint logSize;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize); glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize]; char* logMsg = new char[logSize];
glGetShaderInfoLog(shader, logSize, NULL, logMsg); glGetShaderInfoLog(shader, logSize, NULL, logMsg);
std::cerr << logMsg << std::endl; std::cerr << logMsg << std::endl;
delete[] logMsg; delete[] logMsg;
} }
void printProgramLinkError(GLuint program) void printProgramLinkError(GLuint program)
{ {
GLint logSize; GLint logSize;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize); glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize]; char* logMsg = new char[logSize];
glGetProgramInfoLog(program, logSize, NULL, logMsg); glGetProgramInfoLog(program, logSize, NULL, logMsg);
std::cerr << logMsg << std::endl; std::cerr << logMsg << std::endl;
delete[] logMsg; delete[] logMsg;
} }
GLuint InitShader(const char* computeShaderFile) GLuint InitShader(const char* computeShaderFile)
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
GLchar* source; GLchar* source;
} shaders[1] = } shaders[1] =
{ {
{ computeShaderFile, GL_COMPUTE_SHADER, NULL } { computeShaderFile, GL_COMPUTE_SHADER, NULL }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for (int i = 0; i < 1; ++i) for (int i = 0; i < 1; ++i)
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if (shaders[i].source == NULL) if (shaders[i].source == NULL)
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader(s.type); GLuint shader = glCreateShader(s.type);
glShaderSource(shader, 1, (const GLchar**)&s.source, NULL); glShaderSource(shader, 1, (const GLchar**)&s.source, NULL);
glCompileShader(shader); glCompileShader(shader);
GLint compiled; GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) if (!compiled)
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
delete[] s.source; delete[] s.source;
glAttachShader(program, shader); glAttachShader(program, shader);
} }
/* link and error check */ /* link and error check */
glLinkProgram(program); glLinkProgram(program);
GLint linked; GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked); glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) if (!linked)
{ {
std::cerr << "Shader program failed to link" << std::endl; std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program); printProgramLinkError(program);
error = true; error = true;
} }
if (error == true) if (error == true)
{ {
return -1; return -1;
} }
/* use program object */ /* use program object */
glUseProgram(program); glUseProgram(program);
return program; return program;
} }
@ -117,294 +117,301 @@ GLuint InitShader(const char* computeShaderFile)
GLuint InitShader(const char* vShaderFile, const char* fShaderFile) GLuint InitShader(const char* vShaderFile, const char* fShaderFile)
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
GLchar* source; GLchar* source;
} shaders[2] = } shaders[2] =
{ {
{ vShaderFile, GL_VERTEX_SHADER, NULL }, { vShaderFile, GL_VERTEX_SHADER, NULL },
{ fShaderFile, GL_FRAGMENT_SHADER, NULL } { fShaderFile, GL_FRAGMENT_SHADER, NULL }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if (shaders[i].source == NULL) if (shaders[i].source == NULL)
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader(s.type); GLuint shader = glCreateShader(s.type);
glShaderSource(shader, 1, (const GLchar**)&s.source, NULL); glShaderSource(shader, 1, (const GLchar**)&s.source, NULL);
glCompileShader(shader); glCompileShader(shader);
GLint compiled; GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) if (!compiled)
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
delete[] s.source; delete[] s.source;
glAttachShader(program, shader); glAttachShader(program, shader);
} }
//set shader attrib locations //set shader attrib locations
const int pos_loc = 0; const int posLoc = 0;
const int tex_coord_loc = 1; const int texCoordLoc = 1;
const int normal_loc = 2; const int normalLoc = 2;
glBindAttribLocation(program, pos_loc, "pos_attrib"); glBindAttribLocation(program, posLoc, "posAttrib");
glBindAttribLocation(program, tex_coord_loc, "tex_coord_attrib"); glBindAttribLocation(program, texCoordLoc, "texCoordAttrib");
glBindAttribLocation(program, normal_loc, "normal_attrib"); glBindAttribLocation(program, normalLoc, "normalAttrib");
/* link and error check */ /* link and error check */
glLinkProgram(program); glLinkProgram(program);
GLint linked; GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked); glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) if (!linked)
{ {
std::cerr << "Shader program failed to link" << std::endl; std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program); printProgramLinkError(program);
error = true; error = true;
} }
if (error == true) if (error == true)
{ {
return -1; return -1;
} }
/* use program object */ /* use program object */
glUseProgram(program); glUseProgram(program);
return program; return program;
} }
// Create a GLSL program object from vertex and fragment shader files // Create a GLSL program object from vertex and fragment shader files
GLuint InitShader(const char* vShaderFile, const char* gShaderFile, const char* fShaderFile) GLuint InitShader(const char* vShaderFile, const char* gShaderFile, const char* fShaderFile)
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
GLchar* source; GLchar* source;
} shaders[3] = } shaders[3] =
{ {
{ vShaderFile, GL_VERTEX_SHADER, NULL }, { vShaderFile, GL_VERTEX_SHADER, NULL },
{ gShaderFile, GL_GEOMETRY_SHADER, NULL }, { gShaderFile, GL_GEOMETRY_SHADER, NULL },
{ fShaderFile, GL_FRAGMENT_SHADER, NULL } { fShaderFile, GL_FRAGMENT_SHADER, NULL }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if (shaders[i].source == NULL) if (shaders[i].source == NULL)
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader(s.type); GLuint shader = glCreateShader(s.type);
glShaderSource(shader, 1, (const GLchar**)&s.source, NULL); glShaderSource(shader, 1, (const GLchar**)&s.source, NULL);
glCompileShader(shader); glCompileShader(shader);
GLint compiled; GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) if (!compiled)
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
delete[] s.source; delete[] s.source;
glAttachShader(program, shader); glAttachShader(program, shader);
} }
//set shader attrib locations //set shader attrib locations
const int pos_loc = 0; const int posLoc = 0;
const int tex_coord_loc = 1; const int texCoordLoc = 1;
const int normal_loc = 2; const int normalLoc = 2;
glBindAttribLocation(program, pos_loc, "pos_attrib"); glBindAttribLocation(program, posLoc, "posAttrib");
glBindAttribLocation(program, tex_coord_loc, "tex_coord_attrib"); glBindAttribLocation(program, texCoordLoc, "texCoordAttrib");
glBindAttribLocation(program, normal_loc, "normal_attrib"); glBindAttribLocation(program, normalLoc, "normalAttrib");
/* link and error check */ /* link and error check */
glLinkProgram(program); glLinkProgram(program);
GLint linked; GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked); glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) if (!linked)
{ {
std::cerr << "Shader program failed to link" << std::endl; std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program); printProgramLinkError(program);
error = true; error = true;
} }
if (error == true) if (error == true)
{ {
return -1; return -1;
} }
/* use program object */ /* use program object */
glUseProgram(program); glUseProgram(program);
return program; return program;
} }
GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* fShaderFile ) GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* fShaderFile )
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
std::string source; std::string source;
} shaders[4] = } shaders[4] =
{ {
{ vShaderFile, GL_VERTEX_SHADER, "" }, { vShaderFile, GL_VERTEX_SHADER, "" },
{ tcShader, GL_TESS_CONTROL_SHADER, "" }, { tcShader, GL_TESS_CONTROL_SHADER, "" },
{ teShader, GL_TESS_EVALUATION_SHADER, "" }, { teShader, GL_TESS_EVALUATION_SHADER, "" },
{ fShaderFile, GL_FRAGMENT_SHADER, "" } { fShaderFile, GL_FRAGMENT_SHADER, "" }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for ( int i = 0; i < 4; ++i ) for ( int i = 0; i < 4; ++i )
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if ( shaders[i].source.length() == 0 ) if ( shaders[i].source.length() == 0 )
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader( s.type ); GLuint shader = glCreateShader( s.type );
const char *c_str = s.source.c_str(); const char *c_str = s.source.c_str();
glShaderSource(shader, 1, (const GLchar**)&c_str, NULL); glShaderSource(shader, 1, (const GLchar**)&c_str, NULL);
glCompileShader( shader ); glCompileShader( shader );
GLint compiled; GLint compiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled ); glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) if ( !compiled )
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
glAttachShader( program, shader ); glAttachShader( program, shader );
} }
/* link and error check */ //set shader attrib locations
glLinkProgram(program); const int posLoc = 0;
const int texCoordLoc = 1;
GLint linked; glBindAttribLocation(program, posLoc, "posAttrib");
glGetProgramiv( program, GL_LINK_STATUS, &linked ); glBindAttribLocation(program, texCoordLoc, "texCoordAttrib");
if ( !linked )
{
std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program);
error = true; /* link and error check */
} glLinkProgram(program);
if(error == true) GLint linked;
{ glGetProgramiv( program, GL_LINK_STATUS, &linked );
return -1; if ( !linked )
} {
std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program);
/* use program object */ error = true;
glUseProgram(program); }
return program; if(error == true)
{
return -1;
}
/* use program object */
glUseProgram(program);
return program;
} }
GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* gShaderFile, const char* fShaderFile ) GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* gShaderFile, const char* fShaderFile )
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
std::string source; std::string source;
} shaders[5] = } shaders[5] =
{ {
{ vShaderFile, GL_VERTEX_SHADER, "" }, { vShaderFile, GL_VERTEX_SHADER, "" },
{ tcShader, GL_TESS_CONTROL_SHADER, "" }, { tcShader, GL_TESS_CONTROL_SHADER, "" },
{ teShader, GL_TESS_EVALUATION_SHADER, "" }, { teShader, GL_TESS_EVALUATION_SHADER, "" },
{ gShaderFile, GL_GEOMETRY_SHADER, "" }, { gShaderFile, GL_GEOMETRY_SHADER, "" },
{ fShaderFile, GL_FRAGMENT_SHADER, "" } { fShaderFile, GL_FRAGMENT_SHADER, "" }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for ( int i = 0; i < 5; ++i ) for ( int i = 0; i < 5; ++i )
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if ( shaders[i].source.length() == 0 ) if ( shaders[i].source.length() == 0 )
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader( s.type ); GLuint shader = glCreateShader( s.type );
const char *c_str = s.source.c_str(); const char *c_str = s.source.c_str();
glShaderSource( shader, 1, (const GLchar**) &c_str, NULL ); glShaderSource( shader, 1, (const GLchar**) &c_str, NULL );
glCompileShader( shader ); glCompileShader( shader );
GLint compiled; GLint compiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled ); glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) if ( !compiled )
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
glAttachShader( program, shader ); glAttachShader( program, shader );
} }
/* link and error check */ /* link and error check */
glLinkProgram(program); glLinkProgram(program);
GLint linked; GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked ); glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) if ( !linked )
{ {
std::cerr << "Shader program failed to link" << std::endl; std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program); printProgramLinkError(program);
error = true; error = true;
} }
if(error == true) if(error == true)
{ {
return -1; return -1;
} }
/* use program object */ /* use program object */
glUseProgram(program); glUseProgram(program);
return program; return program;
} }

View File

@ -25,7 +25,7 @@
#include "scene.h" #include "scene.h"
#include "camera.h" #include "camera.h"
#include "Uniforms.h" #include "uniforms.h"
#include "InitShader.h" #include "InitShader.h"
#include "DebugCallback.h" #include "DebugCallback.h"
#include "load_texture.h" #include "load_texture.h"
@ -139,7 +139,7 @@ void Scene::GenerateGrid(int divisions, std::vector<Vertex>& verts, std::vector<
// Currently creates a test triangle and initializes its buffers // Currently creates a test triangle and initializes its buffers
void Scene::InitBuffers() { void Scene::InitBuffers() {
int divisions = 16; // Number of divisions along one axis of the grid int divisions = Uniforms::GeoData.gridDensity; // Number of divisions along one axis of the grid
GenerateGrid(divisions, vertices, indices); GenerateGrid(divisions, vertices, indices);
// Create and bind VAO, VBO, and EBO, and pass the data to OpenGL // Create and bind VAO, VBO, and EBO, and pass the data to OpenGL
@ -225,11 +225,10 @@ void Scene::Display(GLFWwindow* window) {
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Uniforms::SceneData.PV = projection_matrix_ * CameraControls::GetViewMatrix(activeCamera_); // Projection-View matrix Uniforms::GeoData.PV = projection_matrix_ * CameraControls::GetViewMatrix(activeCamera_); // Projection-View matrix
Uniforms::BufferSceneData(); Uniforms::BufferSceneData();
glm::mat4 model_matrix = glm::rotate(angle_, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::scale(glm::vec3(scale_)); Uniforms::GeoData.M = glm::rotate(angle_, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::scale(glm::vec3(scale_));
glUniformMatrix4fv(Uniforms::UniformLocs::M, 1, false, glm::value_ptr(model_matrix));
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_id); glBindTexture(GL_TEXTURE_2D, tex_id);
@ -336,7 +335,8 @@ void Scene::DrawGui(GLFWwindow* window) {
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::SliderFloat("Tessellation Level", &tessellationFactor, 1.0f, 64.0f); ImGui::SliderFloat("Tessellation Level", &Uniforms::GeoData.maxTessellation, 1.0f, 64.0f);
ImGui::SliderInt("Patch Grid Density", &Uniforms::GeoData.gridDensity, 1, 24);
ImGui::End(); ImGui::End();
// Draw FBO to ImGui window // Draw FBO to ImGui window

View File

@ -1,4 +1,4 @@
#include "Uniforms.h" #include "uniforms.h"
#include <GL/glew.h> #include <GL/glew.h>
namespace Uniforms namespace Uniforms
@ -6,11 +6,13 @@ namespace Uniforms
SceneUniforms SceneData; SceneUniforms SceneData;
LightUniforms LightData; LightUniforms LightData;
MaterialUniforms MaterialData; MaterialUniforms MaterialData;
GeoUniforms GeoData;
//IDs for the buffer objects holding the uniform block data //IDs for the buffer objects holding the uniform block data
GLuint scene_ubo = -1; GLuint sceneUbo = 0;
GLuint light_ubo = -1; GLuint lightUbo = 0;
GLuint material_ubo = -1; GLuint materialUbo = 0;
GLuint geoUbo = 0;
namespace UboBinding namespace UboBinding
{ {
@ -18,6 +20,7 @@ namespace Uniforms
int scene = 0; int scene = 0;
int light = 1; int light = 1;
int material = 2; int material = 2;
int geometry = 4;
}; };
//Locations for the uniforms which are not in uniform blocks //Locations for the uniforms which are not in uniform blocks
@ -30,28 +33,37 @@ namespace Uniforms
void Init() void Init()
{ {
//Create and initialize uniform buffers //Create and initialize uniform buffers
glGenBuffers(1, &Uniforms::scene_ubo); glGenBuffers(1, &Uniforms::sceneUbo);
glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo); glBindBuffer(GL_UNIFORM_BUFFER, sceneUbo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneUniforms), nullptr, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneUniforms), nullptr, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null).
glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::scene, scene_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::scene, sceneUbo); //Associate this uniform buffer with the uniform block in the shader that has the same binding.
glGenBuffers(1, &light_ubo); glGenBuffers(1, &lightUbo);
glBindBuffer(GL_UNIFORM_BUFFER, light_ubo); glBindBuffer(GL_UNIFORM_BUFFER, lightUbo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniforms), &LightData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniforms), &LightData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null).
glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::light, light_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::light, lightUbo); //Associate this uniform buffer with the uniform block in the shader that has the same binding.
glGenBuffers(1, &material_ubo); glGenBuffers(1, &materialUbo);
glBindBuffer(GL_UNIFORM_BUFFER, material_ubo); glBindBuffer(GL_UNIFORM_BUFFER, materialUbo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialUniforms), &MaterialData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialUniforms), &MaterialData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null).
glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::material, material_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::material, materialUbo); //Associate this uniform buffer with the uniform block in the shader that has the same binding.
glGenBuffers(1, &geoUbo);
glBindBuffer(GL_UNIFORM_BUFFER, geoUbo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(GeoUniforms), &GeoData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null).
glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::geometry, geoUbo); //Associate this uniform buffer with the uniform block in the shader that has the same binding.
glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBuffer(GL_UNIFORM_BUFFER, 0);
} }
void BufferSceneData() void BufferSceneData()
{ {
glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo); //Bind the OpenGL UBO before we update the data. glBindBuffer(GL_UNIFORM_BUFFER, sceneUbo); //Bind the OpenGL UBO before we update the data.
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(SceneData), &SceneData); //Upload the new uniform values. glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(SceneData), &SceneData); //Upload the new uniform values.
glBindBuffer(GL_UNIFORM_BUFFER, 0); //unbind the ubo glBindBuffer(GL_UNIFORM_BUFFER, 0); //unbind the ubo
glBindBuffer(GL_UNIFORM_BUFFER, geoUbo); //Bind the OpenGL UBO before we update the data.
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GeoData), &GeoData); //Upload the new uniform values.
glBindBuffer(GL_UNIFORM_BUFFER, 0); //unbind the ubo
} }
}; };