Make it possible ot have different shaders along scene graph

This commit is contained in:
Peder Bergebakken Sundt 2019-03-15 16:43:51 +01:00
parent 88376587e5
commit da7a29a2d1
3 changed files with 55 additions and 22 deletions

View File

@ -17,12 +17,12 @@ uniform bool isTextured;
uniform bool isNormalMapped; uniform bool isNormalMapped;
uniform bool isInverted; uniform bool isInverted;
// point lights // lights
struct Light { struct Light {
vec3 position; vec3 position;
mat4 MV; mat4 MV;
bool is_spot; bool is_spot; // false means point light
vec3 spot_target; // MV space coordinates vec3 spot_target; // MV space coordinates for spots
}; };
//named //named

View File

@ -48,7 +48,10 @@ double ballRadius = 3.0f;
// These are heap allocated, because they should not be initialised at the start of the program // These are heap allocated, because they should not be initialised at the start of the program
sf::Sound* sound; sf::Sound* sound;
sf::SoundBuffer* buffer; sf::SoundBuffer* buffer;
Gloom::Shader* shader; Gloom::Shader* default_shader;
Gloom::Shader* test_shader;
Gloom::Shader* plain_shader;
Gloom::Shader* post_shader;
const vec3 boxDimensions(180, 90, 50); const vec3 boxDimensions(180, 90, 50);
const vec3 padDimensions(30, 3, 40); const vec3 padDimensions(30, 3, 40);
@ -109,10 +112,10 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
glfwSetCursorPosCallback(window, mouseCallback); glfwSetCursorPosCallback(window, mouseCallback);
shader = new Gloom::Shader(); // load shaders
shader->makeBasicShader("../res/shaders/simple.vert", "../res/shaders/simple.frag"); default_shader = new Gloom::Shader();
shader->activate(); default_shader->makeBasicShader("../res/shaders/simple.vert", "../res/shaders/simple.frag");
Mesh box = generateBox(boxDimensions.x, boxDimensions.y, boxDimensions.z, true); Mesh box = generateBox(boxDimensions.x, boxDimensions.y, boxDimensions.z, true);
Mesh pad = generateBox(padDimensions.x, padDimensions.y, padDimensions.z, false); Mesh pad = generateBox(padDimensions.x, padDimensions.y, padDimensions.z, false);
Mesh sphere = generateSphere(1.0, 40, 40); Mesh sphere = generateSphere(1.0, 40, 40);
@ -391,39 +394,66 @@ void updateFrame(GLFWwindow* window) {
void renderNode(SceneNode* node) { void renderNode(SceneNode* node) {
struct Light { // lights as stored in the shader
glm::vec3 position;
glm::mat4 MV;
bool is_spot;
glm::vec3 spot_target; // MV space coordinates
void push_to_shader(Gloom::Shader* shader, uint id) {
#define l(x) shader->location("light[" + std::to_string(id) + "]." + #x)
glUniformMatrix4fv(l(MV) , 1, GL_FALSE, glm::value_ptr(MV));
glUniform3fv (l(position) , 1, glm::value_ptr(position));
glUniform3fv (l(spot_target), 1, glm::value_ptr(spot_target));
glUniform1i (l(is_spot) , is_spot);
#undef l
}
};
static Light lights[3];
static Gloom::Shader* s = nullptr; // The currently active shader
// activate the correct shader
Gloom::Shader* node_shader = (node->shader != nullptr)
? node->shader
: default_shader;
if (s != node_shader) {
s = node_shader;
s->activate();
uint i = 0; for (Light l : lights) l.push_to_shader(s, i++);
}
// load uniforms
glUniformMatrix4fv(s->location("MVP") , 1, GL_FALSE, glm::value_ptr(node->MVP)); glUniformMatrix4fv(s->location("MVP") , 1, GL_FALSE, glm::value_ptr(node->MVP));
glUniformMatrix4fv(s->location("MV") , 1, GL_FALSE, glm::value_ptr(node->MV)); glUniformMatrix4fv(s->location("MV") , 1, GL_FALSE, glm::value_ptr(node->MV));
glUniformMatrix4fv(s->location("MVnormal"), 1, GL_FALSE, glm::value_ptr(node->MVnormal)); glUniformMatrix4fv(s->location("MVnormal"), 1, GL_FALSE, glm::value_ptr(node->MVnormal));
glUniform1ui(shader->location("isNormalMapped"), false); glUniform1ui(s->location("isNormalMapped"), false);
glUniform1ui(shader->location("isTextured"), false); glUniform1ui(s->location("isTextured"), false);
switch(node->nodeType) { switch(node->nodeType) {
case NORMAL_TEXTURED_GEOMETRY: case NORMAL_TEXTURED_GEOMETRY:
glUniform1ui(shader->location("isNormalMapped"), true); glUniform1ui(s->location("isNormalMapped"), true);
glBindTextureUnit(1, node->normalTextureID); glBindTextureUnit(1, node->normalTextureID);
[[fallthrough]]; [[fallthrough]];
case TEXTURED_GEOMETRY: case TEXTURED_GEOMETRY:
glUniform1ui(shader->location("isTextured"), true); glUniform1ui(s->location("isTextured"), true);
glBindTextureUnit(0, node->diffuseTextureID); glBindTextureUnit(0, node->diffuseTextureID);
[[fallthrough]]; [[fallthrough]];
case GEOMETRY: case GEOMETRY:
if(node->vertexArrayObjectID != -1) { if(node->vertexArrayObjectID != -1) {
glUniform1ui(shader->location("isIlluminated"), node->isIlluminated); glUniform1ui(s->location("isIlluminated"), node->isIlluminated);
glUniform1ui(shader->location("isInverted"), node->isInverted); glUniform1ui(s->location("isInverted"), node->isInverted);
glBindVertexArray(node->vertexArrayObjectID); glBindVertexArray(node->vertexArrayObjectID);
glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr); glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr);
} }
break; break;
case SPOT_LIGHT: case SPOT_LIGHT:
case POINT_LIGHT: { case POINT_LIGHT: {
std::string pre = "light[" + std::to_string(node->lightID) + "]"; uint id = node->lightID;
lights[id].position = node->position;
glUniform3fv(shader->location(pre+".position"), 1, glm::value_ptr(node->position)); lights[id].MV = node->MV;
glUniformMatrix4fv(shader->location(pre+".MV"), 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrixMV)); lights[id].is_spot = node->nodeType == SPOT_LIGHT;
lights[id].spot_target = node->rotation;
glUniform1i(shader->location(pre+".is_spot"), node->nodeType == SPOT_LIGHT); lights[id].push_to_shader(s, id);
glUniform3fv(shader->location(pre+".spot_target"), 1, glm::value_ptr(node->rotation));
break; break;
} }
case HUD: case HUD:

View File

@ -44,6 +44,9 @@ struct SceneNode {
glm::vec3 rotation; glm::vec3 rotation;
glm::vec3 scale; glm::vec3 scale;
// set this if the shape uses a custom shader other than the default one
Gloom::Shader* shader = nullptr;
// A transformation matrix representing the transformation of the node's location relative to its parent. This matrix is updated every frame. // A transformation matrix representing the transformation of the node's location relative to its parent. This matrix is updated every frame.
glm::mat4 MVP; // MVP glm::mat4 MVP; // MVP
glm::mat4 MV; // MV glm::mat4 MV; // MV