diff --git a/build/osx/Roll them Bones.xcodeproj/project.pbxproj b/build/osx/Roll them Bones.xcodeproj/project.pbxproj index 2cdfba4..28073c7 100644 --- a/build/osx/Roll them Bones.xcodeproj/project.pbxproj +++ b/build/osx/Roll them Bones.xcodeproj/project.pbxproj @@ -14,6 +14,9 @@ 2056AE3E1A8A421500833760 /* Vec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2056AE3A1A8A421500833760 /* Vec.cpp */; }; 205D36CE1A6749FB00C05BD8 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 205D36CD1A6749FB00C05BD8 /* main.cpp */; }; 205D370C1A674B1D00C05BD8 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 205D370B1A674B1D00C05BD8 /* OpenGL.framework */; }; + 206662951A9305FF00631FC0 /* fb_fs.glsl in Copy Shaders */ = {isa = PBXBuildFile; fileRef = 209930A31A92CAB10089E661 /* fb_fs.glsl */; }; + 206662961A9305FF00631FC0 /* fb_vs.glsl in Copy Shaders */ = {isa = PBXBuildFile; fileRef = 209930A41A92CAB10089E661 /* fb_vs.glsl */; }; + 209930831A92ADB00089E661 /* Program.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 209930811A92ADB00089E661 /* Program.cpp */; }; 20A7A8D51A89E11200EDC1A0 /* RenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20A7A8D11A89E11200EDC1A0 /* RenderScene.cpp */; }; 20A7A8D61A89E11200EDC1A0 /* RenderSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20A7A8D31A89E11200EDC1A0 /* RenderSet.cpp */; }; 20A8CE541A899B72004D2504 /* RenderCamera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20A8CE501A899B72004D2504 /* RenderCamera.cpp */; }; @@ -23,6 +26,31 @@ 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + 204FF23E1A93F28B0006E1F0 /* Copy Models */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = data/models; + dstSubfolderSpec = 7; + files = ( + ); + name = "Copy Models"; + runOnlyForDeploymentPostprocessing = 0; + }; + 209930BA1A92CB1C0089E661 /* Copy Shaders */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = data/shaders; + dstSubfolderSpec = 7; + files = ( + 206662951A9305FF00631FC0 /* fb_fs.glsl in Copy Shaders */, + 206662961A9305FF00631FC0 /* fb_vs.glsl in Copy Shaders */, + ); + name = "Copy Shaders"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 20020C6F1A8A01EE00F985D8 /* common.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = common.hpp; path = ../../src/common.hpp; sourceTree = SOURCE_ROOT; }; @@ -36,6 +64,10 @@ 2056AE3B1A8A421500833760 /* Vec.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Vec.hpp; path = ../../src/Vec.hpp; sourceTree = SOURCE_ROOT; }; 205D36CD1A6749FB00C05BD8 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../../src/main.cpp; sourceTree = SOURCE_ROOT; }; 205D370B1A674B1D00C05BD8 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; + 209930811A92ADB00089E661 /* Program.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Program.cpp; path = ../../src/Program.cpp; sourceTree = SOURCE_ROOT; }; + 209930821A92ADB00089E661 /* Program.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Program.hpp; path = ../../src/Program.hpp; sourceTree = SOURCE_ROOT; }; + 209930A31A92CAB10089E661 /* fb_fs.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fb_fs.glsl; sourceTree = ""; }; + 209930A41A92CAB10089E661 /* fb_vs.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fb_vs.glsl; sourceTree = ""; }; 20A7A8D11A89E11200EDC1A0 /* RenderScene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RenderScene.cpp; path = ../../src/RenderScene.cpp; sourceTree = SOURCE_ROOT; }; 20A7A8D21A89E11200EDC1A0 /* RenderScene.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RenderScene.hpp; path = ../../src/RenderScene.hpp; sourceTree = SOURCE_ROOT; }; 20A7A8D31A89E11200EDC1A0 /* RenderSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RenderSet.cpp; path = ../../src/RenderSet.cpp; sourceTree = SOURCE_ROOT; }; @@ -69,6 +101,8 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 209930811A92ADB00089E661 /* Program.cpp */, + 209930821A92ADB00089E661 /* Program.hpp */, 20E3F2901A8CE8470071FD41 /* Log.cpp */, 20E3F2911A8CE8470071FD41 /* Log.hpp */, 20E3F2921A8CE8470071FD41 /* Mesh.cpp */, @@ -88,8 +122,12 @@ 20A8CE521A899B72004D2504 /* RenderView.cpp */, 20A8CE531A899B72004D2504 /* RenderView.hpp */, ); + indentWidth = 2; name = Classes; sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + wrapsLines = 1; }; 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { isa = PBXGroup; @@ -122,12 +160,35 @@ children = ( 205D36CD1A6749FB00C05BD8 /* main.cpp */, ); + indentWidth = 2; name = Sources; sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + wrapsLines = 1; + }; + 2099309F1A92CAB10089E661 /* data */ = { + isa = PBXGroup; + children = ( + 209930A01A92CAB10089E661 /* shaders */, + ); + name = data; + path = ../../data; + sourceTree = SOURCE_ROOT; + }; + 209930A01A92CAB10089E661 /* shaders */ = { + isa = PBXGroup; + children = ( + 209930A31A92CAB10089E661 /* fb_fs.glsl */, + 209930A41A92CAB10089E661 /* fb_vs.glsl */, + ); + path = shaders; + sourceTree = ""; }; 29B97314FDCFA39411CA2CEA /* INDIE */ = { isa = PBXGroup; children = ( + 2099309F1A92CAB10089E661 /* data */, 205D36C31A6749DF00C05BD8 /* Sources */, 080E96DDFE201D6D7F000001 /* Classes */, 29B97315FDCFA39411CA2CEA /* Other Sources */, @@ -143,8 +204,11 @@ children = ( 20020C6F1A8A01EE00F985D8 /* common.hpp */, ); + indentWidth = 2; name = "Other Sources"; sourceTree = ""; + tabWidth = 2; + usesTabs = 0; }; 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; @@ -172,6 +236,8 @@ 8D1107290486CEB800E47090 /* Resources */, 8D11072C0486CEB800E47090 /* Sources */, 8D11072E0486CEB800E47090 /* Frameworks */, + 209930BA1A92CB1C0089E661 /* Copy Shaders */, + 204FF23E1A93F28B0006E1F0 /* Copy Models */, ); buildRules = ( ); @@ -235,6 +301,7 @@ 2056AE3E1A8A421500833760 /* Vec.cpp in Sources */, 20E3F2941A8CE8470071FD41 /* Log.cpp in Sources */, 20E3F2951A8CE8470071FD41 /* Mesh.cpp in Sources */, + 209930831A92ADB00089E661 /* Program.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/data/shaders/fb_fs.glsl b/data/shaders/fb_fs.glsl new file mode 100644 index 0000000..ca8fa15 --- /dev/null +++ b/data/shaders/fb_fs.glsl @@ -0,0 +1,13 @@ +#version 120 + +// in +varying vec2 UV; + +uniform sampler2D tex1; + +// +void main() { + gl_FragColor = vec4(texture2D(tex1, UV).xyz, 1.0); + //gl_FragColor = vec4(UV.xy, 1.0, 1.0); + //gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); +} diff --git a/data/shaders/fb_vs.glsl b/data/shaders/fb_vs.glsl new file mode 100644 index 0000000..f381c26 --- /dev/null +++ b/data/shaders/fb_vs.glsl @@ -0,0 +1,11 @@ +#version 120 +// in +attribute vec3 vp; +// out +varying vec2 UV; + +void main() { + gl_Position = vec4(vp, 1.0); + UV = (vp.xy + vec2(1.0, 1.0)) / 2.0; + ///UV = vp.xy; +} diff --git a/src/Mesh.cpp b/src/Mesh.cpp index e910e8e..8e2f12f 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -4,11 +4,14 @@ #include // atof Mesh::Mesh() { - vbo = vao = tex = 0; + uvbo = vbo = vao = tex = 0; flags = 0; mode = GL_STATIC_DRAW; } Mesh::Mesh(Vec3 *in_vertices, int v_count, Vec2 *in_uvs, int uv_count, Vec3 *in_normals, int n_count) { + uvbo = vbo = vao = tex = 0; + flags = 0; + mode = GL_STATIC_DRAW; loadArrays(in_vertices, v_count, in_uvs, uv_count, in_normals, n_count); } @@ -211,15 +214,15 @@ int Mesh::loadArrays(Vec3 *in_vertices, int v_count, Vec2 *in_uvs, int uv_count, int Mesh::buildMesh() { if (!(flags & MESH_LOADED)) return 1; if (flags & MESH_BUILT) destroyMesh(); - // generate our vertex array object - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); // generate our vertex buffer object from our given points glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vec3), &vertices[0], mode); - // unbind vao to disallow external mucking - glBindVertexArray(0); + // generate our uvs buffer object + glGenBuffers(1, &uvbo); + glBindBuffer(GL_ARRAY_BUFFER, uvbo); + glBufferData(GL_ARRAY_BUFFER, uvs.size()*sizeof(Vec2), &uvs[0], mode); + flags |= MESH_BUILT; return 0; } @@ -228,4 +231,4 @@ int Mesh::destroyMesh() { //glDeleteVertexArrays(1, &vao); flags &= ~MESH_BUILT; return 0; -} \ No newline at end of file +} diff --git a/src/Mesh.hpp b/src/Mesh.hpp index bb2e065..69e55b5 100644 --- a/src/Mesh.hpp +++ b/src/Mesh.hpp @@ -22,17 +22,18 @@ class Mesh { int loadArrays(Vec3 *in_vertices, int v_count, Vec2 *in_uvs, int uv_count, Vec3 *in_normals, int n_count); int buildMesh(); int destroyMesh(); - private: - unsigned int flags; // Flags to signify our status // the base sources of our mesh std::vector vertices; std::vector uvs; std::vector normals; + GLuint vao; // our mesh vertex attribute object + GLuint vbo; // our mesh vertex buffer object + GLuint uvbo; // our mesh uv buffer object + private: + unsigned int flags; // Flags to signify our status // reference to GPU objects GLuint tex; // our texture to use - GLuint vao; // our mesh vertex attribute object GLuint mode; // Our BufferData mode, either (default)GL_STATIC_DRAW or GL_DYNAMIC_DRAW protected: - GLuint vbo; // our mesh vertex buffer object }; -#endif \ No newline at end of file +#endif diff --git a/src/Program.cpp b/src/Program.cpp new file mode 100644 index 0000000..558179b --- /dev/null +++ b/src/Program.cpp @@ -0,0 +1,158 @@ +/* ================================================================ +Program +---------------- +This file defines our Program class. This class is responsible for +loading, creating, and compiling OpenGL programs. +================================================================ */ +#include "Program.hpp" +#include "Log.hpp" +#include +#include // oor +/* ======== Constructors and Destructors ======== */ +Program::Program() { + program = 0; +} +Program::~Program() { + doClean(); +} +/* ======== Compilation and Linking ======== */ +// add given shader to Program. During doCompile(), it is compiled and attached to the program +int Program::addShader(const char *file, GLenum type) { + // Load in our shader file + std::ifstream in(file); + if (!in) { + LOG(LOG_ERROR) << FUNC_NAME << ": Could not open \"" << file << "\" for reading"; + return 1; + } + std::string contents((std::istreambuf_iterator(in)), std::istreambuf_iterator()); + // Create our shader + GLuint shader = glCreateShader(type); + if (shader == 0) { + LOG(LOG_ERROR) << FUNC_NAME << ": Could not create shader for " << file; + return 2; + } + // Load GLSL program into OpenGL + const char *c_str = contents.c_str(); + glShaderSource(shader, 1, &c_str, NULL); + // Push the shader and its type onto the appropriate vectors + shader_prog.push_back(shader); + shader_type.push_back(type); + return 0; +} +int Program::doCompile() { + int params = -1; // param return for error checking + char log[2048]; // log for OpenGL info logs + int len = 0; // length of logs + // Let's first create our program + program = glCreateProgram(); + // Now we compile our shaders + int i; + for (i = 0; i < shader_prog.size(); i++) { + GLuint shader = shader_prog.at(i); + glCompileShader(shader); + // Let's check for errors + glGetShaderiv(shader, GL_COMPILE_STATUS, ¶ms); + if (params == GL_FALSE) { + glGetShaderInfoLog(shader, 2048, &len, log); + LOG(LOG_ERROR) << FUNC_NAME << ": shader \'" << shader << "\' failed to compile!\n" << log; + return 1; + } + glAttachShader(program, shader); + LOG(LOG_INFO) << FUNC_NAME << ": shader \'" << shader << "\' built and attached to " << program; + } + // Let's link the program + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, ¶ms); + if (params != GL_TRUE) { + glGetProgramInfoLog(program, 2048, &len, log); + LOG(LOG_ERROR) << FUNC_NAME << ": failed to link program " << program << "\n" << log; + return 1; + } + LOG(LOG_INFO) << FUNC_NAME << ": program " << program << " successfully built"; + return 0; +} +GLuint Program::getProgram() { + return program; +} +/* ======== (De)Activation ======== */ +// +int Program::activate() { + glUseProgram(program); + // TODO: foreach texture, activate and bind + /*glActiveTexture(r_texture++); + glBindTexture(GL_TEXTURE_2D, r_view->getFBO()); + // FIXME: not sure how else this should be done! + char texture_str[7]; + snprintf(texture_str, 7, "tex%d", r_texture); + glUniform1i(glGetUniformLocation(program->getProgram(), texture_str), r_texture-1);*/ + int i; + for (i = 0; i < shader_textures.size(); i++) { + glActiveTexture(GL_TEXTURE0 + shader_textures[i].index); + glBindTexture(GL_TEXTURE_2D, shader_textures[i].texture); + glUniform1i(shader_textures[i].location, shader_textures[i].index); + } + return 0; +} +int Program::deactivate() { + // TODO: deactivate textures + int i; + for (i = 0; i < shader_textures.size(); i++) { + // ?? FIXME + } + return 0; +} +/* ======== Cleaning ======== */ +int Program::doClean() { + // TODO: glDetachShader + // TODO: glDeleteProgram + return 0; +} +/* ======== Variable interfaces ======== */ +// Textures can be "inserted" into a Program via the following function. The texture index position corresponds to an OpenGL texture position as well as the GLSL uniform that matches "tex"+"1-99" (e.g., "tex1"). +int Program::attachTexture(GLuint index, GLuint texture) { + if (texture == 0) return 1; + char texture_str[7]; + snprintf(texture_str, 7, "tex%d", index); + + Texture tex; + tex.index = index; + tex.texture = texture; + tex.location = glGetUniformLocation(program, texture_str); + + // Insert it onto the textures record for later usage + shader_textures.insert(shader_textures.begin()+index, tex); + + return 0; +} +int Program::setTexture(GLuint index, GLuint texture) { + try { + shader_textures.at(index).texture = texture; + } catch (const std::out_of_range& oor) { + LOG(LOG_WARNING) << FUNC_NAME << ": " << oor.what(); + return 1; + } + return 0; +} +GLuint Program::getUniform(const char *name) { + return 0; +} +// VARIABLE +Program::Variable::Variable(VariableType type_) { + data_type = type_; + type = UNDEF; + location = 0; + data = NULL; + length = 0; + switch(data_type) { + case TEXTURE: + length = sizeof(GLuint); + data = (char*)malloc(length); + (*data) = (GLuint)0; + break; + case INT: + break; + } +} +Program::Variable::~Variable() { + if (data != NULL) free(data); +} \ No newline at end of file diff --git a/src/Program.hpp b/src/Program.hpp new file mode 100644 index 0000000..ebc7ddd --- /dev/null +++ b/src/Program.hpp @@ -0,0 +1,59 @@ +/* ================================================================ +Program +---------------- +This file describes our Program class. This class is responsible for +loading, creating, and compiling OpenGL programs. +================================================================ */ +#ifndef PROGRAM_HPP +#define PROGRAM_HPP +#include "common.hpp" +#include +class Program { + // + public: + class Variable { + friend class Program; + public: + enum VariableType { + UNDEF, INT, UINT, FLOAT, DOUBLE, TEXTURE + }; + Variable(VariableType type); + ~Variable(); + protected: + int type; // 0 = uniform, 1 = attribute + GLint location; + int data_type; + char *data; + size_t length; + }; + class Texture { + friend class Program; + public: + Texture() { location = -1; index = 0; texture = 0;}; + protected: + GLint location; + GLuint index; + GLuint texture; + }; + public: + Program(); + ~Program(); + int addShader(const char *file, GLenum type); + int attachTexture(GLuint index, GLuint texture); + int setTexture(GLuint index, GLuint texture); + int doCompile(); + int doClean(); + GLuint getUniform(const char *name); + GLuint getProgram(); + int activate(); + int deactivate(); + protected: + GLuint program; // Compiled shader program + private: + std::vector shader_type; // Type of shader program, tied to v + std::vector shader_prog; // Compiled shader program, tied to ^ + std::vector shader_uniform; // Shader uniform locations + std::vector shader_textures;// Textures that this shader uses + std::vector shader_variables; +}; +#endif diff --git a/src/RenderScene.cpp b/src/RenderScene.cpp index cf261b8..829313b 100644 --- a/src/RenderScene.cpp +++ b/src/RenderScene.cpp @@ -17,7 +17,11 @@ RenderScene::RenderScene() { RenderScene::~RenderScene() { } -int RenderScene::renderTo(RenderView *target_view) { +/* renderTo + This function attempts to render the given scene to the target_view using the contained RenderCamera(s). + It iterates over all RenderSets and their RenderObjects and attempts to render to the RenderCamera's attached RenderViews. +*/ +int RenderScene::renderTo(RenderView *target_view, Program *render_program) { RenderCamera *camera; RenderView *view; RenderSet *set; @@ -38,9 +42,48 @@ int RenderScene::renderTo(RenderView *target_view) { } } } + // Use this provided program for rendering. Should refer to a framebuffer shader + glUseProgram(render_program->getProgram()); + // Bind to the provided target view's fbo + glBindFramebuffer(GL_FRAMEBUFFER, view->fbo); + // Render each of our camera's framebuffers with the appropriate changes + for (camera_it = cameras.begin(), camera_end = cameras.end(); camera_it != camera_end; ++camera_it) { + camera = *camera_it; + if ((view = camera->getRenderView()) == NULL) continue; + glBindFramebuffer(GL_FRAMEBUFFER, view->fbo); + } return 0; } +int RenderScene::doRender() { + RenderCamera *camera; + RenderView *view; + RenderSet *set; + RenderObject *object; + std::vector::iterator camera_it, camera_end; + for (camera_it = cameras.begin(), camera_end = cameras.end(); camera_it != camera_end; ++camera_it) { + camera = *camera_it; + if ((view = camera->getRenderView()) == NULL) continue; + glBindFramebuffer(GL_FRAMEBUFFER, view->fbo); + glClearColor(0.75f, 0.25f, 0.25f, 0.5f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + std::vector::iterator set_it, set_end; + for (set_it = sets.begin(), set_end = sets.end(); set_it != set_end; ++set_it) { + set = *set_it; + if (set->program == NULL) continue; + glUseProgram(set->program->getProgram()); + std::vector::iterator obj_it, obj_end; + for (obj_it = set->objects.begin(), obj_end = set->objects.end(); obj_it != obj_end; ++obj_it) { + object = *obj_it; + // TODO: if object is not in camera's view, continue (probably reverse projection on each corner) + // TODO: enable and attach texture + // TODO: enable vp, uv, normals, and send to shader! + // TODO: maybe other things? Should this be managed by Program somehow? + } + } + } + return 0; +} // This function adds the ptr to Camera and returns its "id" which is simply its index+1 int RenderScene::addCamera(RenderCamera* camera) { try { @@ -78,3 +121,6 @@ RenderCamera* RenderScene::getCamera(int id) { } return NULL; } +std::vector *RenderScene::getCameras() { + return &cameras; +} diff --git a/src/RenderScene.hpp b/src/RenderScene.hpp index 2fc143f..50ff34b 100644 --- a/src/RenderScene.hpp +++ b/src/RenderScene.hpp @@ -12,16 +12,19 @@ each of which correspond to a different scene perspective. #include "common.hpp" #include "RenderCamera.hpp" #include "RenderSet.hpp" +#include "Program.hpp" #include class RenderScene { public: RenderScene(); ~RenderScene(); - int renderTo(RenderView *view); + int doRender(); + int renderTo(RenderView *target_view, Program *render_program); int addCamera(RenderCamera* camera); int remCamera(RenderCamera* camera); int remCamera(int id); RenderCamera* getCamera(int id); + std::vector *getCameras(); private: std::vector cameras; // Our scene's cameras std::vector sets; // Our scene's render sets diff --git a/src/RenderSet.cpp b/src/RenderSet.cpp index 7f4181b..4895c8f 100644 --- a/src/RenderSet.cpp +++ b/src/RenderSet.cpp @@ -6,6 +6,7 @@ This header file defines the RenderSet class. #include "RenderSet.hpp" /* ======== Constructors and Destructors ======== */ RenderSet::RenderSet() { + program = NULL; } RenderSet::~RenderSet() { } \ No newline at end of file diff --git a/src/RenderSet.hpp b/src/RenderSet.hpp index 9881a0a..bd25918 100644 --- a/src/RenderSet.hpp +++ b/src/RenderSet.hpp @@ -12,6 +12,7 @@ rendering layers of the program. #define RENDERSET_HPP #include "common.hpp" #include "RenderObject.hpp" +#include "Program.hpp" #include class RenderSet { friend class RenderScene; @@ -20,7 +21,7 @@ class RenderSet { ~RenderSet(); private: int mode; // bitflag, 0 = normal, 1 = hide - GLuint program; // Our rendering program + Program *program; // Our rendering program protected: std::vector objects; // Our vector of objects to render }; diff --git a/src/RenderView.cpp b/src/RenderView.cpp index 3e93034..07fab24 100644 --- a/src/RenderView.cpp +++ b/src/RenderView.cpp @@ -7,7 +7,7 @@ This file defines our RenderView object. #include "Log.hpp" /* ======== Constructors and Destructors ======== */ RenderView::RenderView(int width, int height) { - program = fbo = fbo_depth = fbo_tex = 0; + fbo = fbo_depth = fbo_tex = 0; w = width; h = height; x = y = 0; @@ -19,6 +19,13 @@ RenderView::~RenderView() { destroyView(); if (mesh != NULL) delete mesh; } +/* ======== Getters ======== */ +GLuint RenderView::getFBO() { + return fbo; +} +Mesh *RenderView::getMesh() { + return mesh; +} /* ======== Setters ======== */ int RenderView::createView(int width, int height) { // TODO: call destroyView() and create new FBO at width and height @@ -73,19 +80,16 @@ int RenderView::createView(int width, int height) { }; mesh = new Mesh(quad, 6, NULL, 0, NULL, 0); mesh->buildMesh(); - // TODO: Create and Compile Framebuffer shader (maybe?) w = width; h = height; return 0; } int RenderView::destroyView() { if ((flags & RENDERVIEW_ACTIVE) == 0) return 1; - //glDeleteProgram(v_fb_program[i]); - //glDeleteTextures(1, &v_fb_program_texture[i]); glDeleteFramebuffers(1, &fbo); glDeleteTextures(1, &fbo_tex); glDeleteRenderbuffers(1, &fbo_depth); + delete mesh; flags &= ~RENDERVIEW_ACTIVE; - // TODO: delete fbo_vao, fbo_vbo return 0; } int RenderView::setView(int width, int height) { @@ -102,4 +106,4 @@ int RenderView::setView(int width, int height) { w = width; h = height; return 0; -} \ No newline at end of file +} diff --git a/src/RenderView.hpp b/src/RenderView.hpp index 892c0fd..a96b876 100644 --- a/src/RenderView.hpp +++ b/src/RenderView.hpp @@ -4,8 +4,7 @@ RenderView This header file describes our RenderView object. A RenderView is the target of a RenderCamera and consists of a framebuffer -object and shader program to render said framebuffer. For all intents and -purposes, it is a wrapper around a FBO. +object. For all intents and purposes, it is a wrapper around a FBO. ================================================================ */ #ifndef RENDERVIEW_HPP #define RENDERVIEW_HPP @@ -17,13 +16,14 @@ class RenderView { public: RenderView(int width, int height); ~RenderView(); + GLuint getFBO(); + Mesh *getMesh(); protected: GLuint fbo; // The fbo that RenderScene will draw to private: int createView(int width, int height); int destroyView(); int setView(int width, int height); - GLuint program; // Compiled shader program to render with GLuint fbo_depth; // The fbo depth buffer GLuint fbo_tex; // The texture of the fbo int w, h; // width and height of this view (also of fbo) @@ -31,4 +31,4 @@ class RenderView { Mesh *mesh; // rendering Mesh, created as quad in CreateView unsigned int flags; // byte flag }; -#endif \ No newline at end of file +#endif diff --git a/src/main.cpp b/src/main.cpp index d58bf6a..48b1777 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,23 @@ #include "common.hpp" +#include "Program.hpp" #include "RenderScene.hpp" #include "RenderView.hpp" #include "RenderCamera.hpp" #include "Log.hpp" +#ifdef __APPLE__ +#include "CoreFoundation/CoreFoundation.h" +#endif + + int main(int argc, char *argv[]) { +#ifdef __APPLE__ + char path[PATH_MAX]; + CFURLRef res = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); + CFURLGetFileSystemRepresentation(res, TRUE, (UInt8 *)path, PATH_MAX); + CFRelease(res); + chdir(path); +#endif // TEMP location of video vars SDL_Window *v_window = NULL; SDL_GLContext v_context = 0; @@ -44,16 +57,36 @@ int main(int argc, char *argv[]) { SDL_GL_MakeCurrent(v_window, v_context); // Get our window's FBO id for iOS glGetIntegerv(GL_FRAMEBUFFER_BINDING, &v_fbo); + // enable depth testing + glEnable(GL_DEPTH_TEST); // + glDepthFunc(GL_LESS); + // enable back-face culling + //glEnable(GL_CULL_FACE); LOG(LOG_INFO) << "OpenGL Renderer: " << glGetString(GL_RENDERER) << "\nOpenGL Version: " << glGetString(GL_VERSION); - glClearColor(0.5f, 0.5f, 0.5f, 0.5f); // - RenderView v_view(v_width, v_height); + // Create our basic RenderScene RenderScene *scene = new RenderScene(); + + Program *program = new Program(); + if (program->addShader("data/shaders/fb_fs.glsl", GL_FRAGMENT_SHADER) != 0) { + LOG(LOG_ERROR) << "Failed to add Shader!"; + return 1; + } + if (program->addShader("data/shaders/fb_vs.glsl", GL_VERTEX_SHADER) != 0) { + LOG(LOG_ERROR) << "Failed to add Shader!"; + return 1; + } + if (program->doCompile() != 0) { + LOG(LOG_ERROR) << "Failed to compile GLSL Program!"; + return 1; + } + int camera_id = scene->addCamera(new RenderCamera()); RenderCamera *camera = scene->getCamera(camera_id); - RenderView *view = new RenderView(v_width, v_height); - camera->setRenderView(view); + camera->setRenderView(new RenderView(v_width, v_height)); + + program->attachTexture(0, camera->getRenderView()->getFBO()); // begin our main loop g_running = 1; @@ -63,16 +96,48 @@ int main(int argc, char *argv[]) { g_running = 0; } } - scene->renderTo(&v_view); + scene->doRender(); // Render our main scene using loaded cameras - glBindFramebuffer(GL_FRAMEBUFFER, v_fbo); + //glBindFramebuffer(GL_FRAMEBUFFER, v_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, v_width, v_height); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - + // Alright, let's render our scene to the screen. We bind textures equal to the # of RenderCamera's Renderviews available. + RenderCamera *r_camera; + RenderView *r_view; + std::vector::iterator camera_it, camera_end; + program->activate(); + for (camera_it = scene->getCameras()->begin(), camera_end = scene->getCameras()->end(); camera_it != camera_end; ++camera_it) { + r_camera = *camera_it; + if ((r_view = camera->getRenderView()) == NULL) continue; + // + GLuint program_p = program->getProgram(); + GLuint program_vp = glGetAttribLocation(program_p, "vp"); + // enable vertex positions and UV map + glEnableVertexAttribArray(program_vp); + // Get our mesh + Mesh *mesh = r_view->getMesh(); + glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo); + glEnableVertexAttribArray(program_vp); + glVertexAttribPointer(program_vp, 3, GL_FLOAT, GL_FALSE, 0, NULL); + // and draw + glDrawArrays(GL_TRIANGLES, 0, mesh->vertices.size()); + // close 'em + glDisableVertexAttribArray(program_vp); + + /*glActiveTexture(r_texture++); + glBindTexture(GL_TEXTURE_2D, r_view->getFBO()); + // FIXME: not sure how else this should be done! + char texture_str[7]; + snprintf(texture_str, 7, "tex%d", r_texture); + glUniform1i(glGetUniformLocation(program->getProgram(), texture_str), r_texture-1);*/ + } + program->deactivate(); + SDL_GL_SwapWindow(v_window); SDL_Delay(1); } SDL_Quit(); return 0; -} \ No newline at end of file +}