Merge branch 'feature/7-codebase-refactoring' into 'main'
Update uniform handling See merge request jack/terravisor!2
This commit is contained in:
commit
5d1d56bc5c
|
@ -0,0 +1,3 @@
|
||||||
|
## [v0.1.1] - 2024-08-25
|
||||||
|
### Changed
|
||||||
|
- Refactored uniform handling in the initial geometry pass to improve maintainability.
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
};
|
};
|
Loading…
Reference in New Issue