diff --git a/game/glclasses.cpp b/game/glclasses.cpp index 6486546..0787a2e 100644 --- a/game/glclasses.cpp +++ b/game/glclasses.cpp @@ -9,7 +9,7 @@ namespace endofthejedi { VAO::~VAO() { glDeleteVertexArrays(1, &m_name); } void VAO::bind() { glBindVertexArray(m_name); } - void VAO::unbind() { glBindVertexArray(0); } + void VAO::unbind() { glBindVertexArray(0); } void VAO::fill(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, diff --git a/game/renderer_polygon_3d/gameobjects.frag b/game/renderer_polygon_3d/gameobjects.frag index 10278bc..8955dae 100644 --- a/game/renderer_polygon_3d/gameobjects.frag +++ b/game/renderer_polygon_3d/gameobjects.frag @@ -4,25 +4,42 @@ R"raw_string( varying vec3 vertex; varying vec3 normal; -uniform vec3 color; -varying vec3 lightvec; +uniform vec3 materialColor; +uniform vec3 lightColor; +uniform vec3 lightPosition; + +varying vec3 lightDirection; void main() { - //gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); - //gl_FragColor = vec4(0.5+0.5*vertex.xyz, 1.0); - - vec3 Eye = normalize(-vertex); - vec3 Reflected = normalize(reflect( -lightvec, normal)); + vec3 Reflected = normalize(reflect( -lightPosition, normal)); -//todo materials (& light color) - vec4 IAmbient = vec4(0.2f, 0.2f, 0.2f, 1.0f); - vec4 IDiffuse = vec4(color, 0.0f) * max(dot(normal, lightvec), 0.0); - //todo shininess - vec4 ISpecular = vec4(1.0f, 0.0f, 0.0f, 0.0f) * pow(max(dot(Reflected, Eye), 0.0), 3); + vec3 IAmbient = vec3(0.2f); - gl_FragColor = vec4((IAmbient + IDiffuse) + ISpecular); + // TODO: add noise texture + vec3 IDiffuse = vec3(materialColor) * lightColor * max(dot(normal, lightDirection), 0.0); + + // TODO make instensity/exponent as parameter + //vec3 ISpecular = lightColor * 5.0 * pow(max(dot(Reflected, Eye), 0.0), 2.0); + vec3 ISpecular = lightColor * pow(max(dot(Reflected, Eye), 0.0), 2.0); + + if (dot(lightDirection, normal) <= 0.0) { + ISpecular = vec3(0.0, 0.0, 0.0); + } + + // p: point of the fragment on the surface + //vec3 v_eye = normalize(pos_eye - pos_space); // point from p to eye + //vec3 v_sun = normalize(sun_light_dir); // points from p to the sun + + //float specular = spec_int * pow( + // clamp(dot((v_eye + v_sun)/2.0, normal), 0.0, 1.0), + // 2.0*specular_exponent); + + //ISpecular = vec3(1.0, 0.0, 0.0) * specular; + + //gl_FragColor = vec4(ISpecular, 1.0); + gl_FragColor = vec4((IAmbient + IDiffuse) + ISpecular, 1.0); //gl_FragColor = vec4(0.5+0.5*normal, 1.0); } )raw_string" diff --git a/game/renderer_polygon_3d/gameobjects.vert b/game/renderer_polygon_3d/gameobjects.vert index 6594746..1d560eb 100644 --- a/game/renderer_polygon_3d/gameobjects.vert +++ b/game/renderer_polygon_3d/gameobjects.vert @@ -6,17 +6,16 @@ attribute vec3 in_normal; varying vec3 vertex; varying vec3 normal; -varying vec3 lightvec; +varying vec3 lightDirection; uniform mat4 model; -uniform vec3 lightpos; +uniform vec3 lightPosition; void main() { - //vec3 p = position + scale*in_vertex.xyz; - + // TODO: this becomes invalid when projection matrices are used vec3 p = (model*vec4(in_vertex, 1.0)).xyz; - lightvec = normalize(lightpos - p); + lightDirection = normalize(lightPosition - p); vertex = p.xyz; normal = normalize((model*vec4(in_normal.xyz, 0.0)).xyz); diff --git a/game/renderer_polygon_3d/polygon_model.cpp b/game/renderer_polygon_3d/polygon_model.cpp index e69de29..e49e1a8 100644 --- a/game/renderer_polygon_3d/polygon_model.cpp +++ b/game/renderer_polygon_3d/polygon_model.cpp @@ -0,0 +1,213 @@ +#include "polygon_model.hpp" + +namespace endofthejedi { + PolygonModel::PolygonModel(const std::string &filename) : m_filename(filename) + { + clear(); + } + + bool PolygonModel::bind(Shader &shader) + { + if (!m_loaded_to_opengl) { + std::cout<<"[polygonmodel] warning: try to bind model vbo " + << "which was not uploaded to OpenGL!" << std::endl; + + exit(-1); + return false; + } + + // bind position vbo + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_position); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); + + // bind normal vbo + GLint loc = glGetAttribLocation(shader.program(), "in_normal"); + glEnableVertexAttribArray(loc); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_normal); + glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, NULL); + + m_binding_active = true; + + return true; + } + + bool PolygonModel::render(Shader& shader) + { + (void) shader; + + if (!m_binding_active || !m_loaded_to_opengl) { + std::cout<<"[polygonmodel] warning: try to render model without bind()" << std::endl; + exit(-1); + return false; + } + + //GLint l0 = glGetAttribLocation(shader.program(), "in_normal"); + //GLint l1 = glGetAttribLocation(shader.program(), "in_vertex"); + //GLint l2 = glGetAttribLocation(shader.program(), "in_fakkkke"); + //std::cout<<"locations: " << l0 << " " << l1 << " " << l2 << std::endl; + + //glBindAttribLocation(shader.program(), 0, "in_vertex"); + //glBindAttribLocation(shader.program(), 1, "in_normal"); + + glDrawArrays(GL_TRIANGLES, 0, m_numVertices); + return true; + } + + bool PolygonModel::copyVertices(const aiScene *scene) + { + if (scene->mMeshes == 0) { + std::cout << "[polygonmodel : no meshes loaded for " << m_filename << std::endl; + return false; + } + + aiNode *node = scene->mRootNode; + const aiMesh* mesh = scene->mMeshes[node->mMeshes[0]]; + + // 3 vertices per face, 3 floats per vertex + m_numVertices = mesh->mNumFaces*3; + + m_data_position.reserve(m_numVertices); + m_data_normal.reserve(m_numVertices); + + size_t t, i; + for (t=0; tmNumFaces; ++t) { + const aiFace* face = &mesh->mFaces[t]; + if (face->mNumIndices != 3) { + std::cout << "[polygonmodel] need triangles, got something different with: " + << face->mNumIndices << " vertices" << std::endl; + + return false; + } + + for (i=0; imNumIndices; i++) { + const size_t index = face->mIndices[i]; + m_data_position.push_back(mesh->mVertices[index].x); + m_data_position.push_back(mesh->mVertices[index].y); + m_data_position.push_back(mesh->mVertices[index].z); + + m_data_normal.push_back(mesh->mNormals[index].x); + m_data_normal.push_back(mesh->mNormals[index].y); + m_data_normal.push_back(mesh->mNormals[index].z); + + //std::cout<<"adding normal: " << mesh->mNormals[index].x << " " << mesh->mNormals[index].y << " " << mesh->mNormals[index].z << std::endl; + } + } + + size_t totalBytes = 3*m_numVertices*sizeof(float); + std::cout<<"[polygonmodel] loaded file " << m_filename + << " with " << m_numVertices << " vertices (" + << totalBytes << " bytes)" << std::endl; + + return true; + } + + bool PolygonModel::uploadToOpenGl() + { + if (!m_loaded_from_file) { + std::cerr<<"[polygonmodel] warning: try to upload model data " + << "to OpenGL but no data is loaded!" << std::endl; + + exit(-1); + return false; + } + + /************************************************************/ + /* Position data */ + /************************************************************/ + + glEnableVertexAttribArray(0); + + glGenBuffers(1, &m_vbo_id_position); // Generate buffer + glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_position); // Bind buffer + + glVertexAttribPointer(0, + 3, // three floats per vertex + GL_FLOAT, // Data is floating point type + GL_FALSE, // No fixed point scaling + 0, // stride: no + NULL); // No offset + + // fill buffer with the loaded mesh position data + glBufferData( + GL_ARRAY_BUFFER, // Buffer target + 3 * m_numVertices * sizeof(float), // Buffer data size + m_data_position.data(), // Buffer data pointer + GL_STATIC_DRAW); // Usage - Data never changes; + + /************************************************************/ + /* Normal data */ + /************************************************************/ + + glEnableVertexAttribArray(1); + glGenBuffers(1, &m_vbo_id_normal); // Generate buffer + glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_normal); // Bind buffer + + glVertexAttribPointer( + 1, + 3, // three floats per normal + GL_FLOAT, // Data is floating point type + GL_FALSE, // No fixed point scaling + 0, // stride: no + NULL); // No offset + + // Fill bound buffer + glBufferData( + GL_ARRAY_BUFFER, // Buffer target + 3 * m_numVertices * sizeof(float), // Buffer data size + m_data_normal.data(), // Buffer data pointer + GL_STATIC_DRAW); // Usage - Data never changes; + + m_loaded_to_opengl = true; + + return true; + } + + bool PolygonModel::import() + { + clear(); + + // Create an instance of the Importer class + Assimp::Importer importer; + // And have it read the given file with some example postprocessing + // Usually - if speed is not the most important aspect for you - you'll + // propably to request more postprocessing than we do in this example. + const aiScene* scene = importer.ReadFile(m_filename, + aiProcess_CalcTangentSpace | + aiProcess_Triangulate | + aiProcess_JoinIdenticalVertices | + aiProcess_SortByPType); + + // If the import failed, report it + if (!scene) { + std::cout<<"[polygonmodel] loading file " + << m_filename << " failed with: " + << importer.GetErrorString() << std::endl; + + return false; + } + + // Now we can access the file's contents. + copyVertices(scene); + + m_loaded_from_file = true; + + // We're done. Everything will be cleaned up by the importer destructor + return true; + } + + void PolygonModel::clear() + { + // TODO: delete buffers if there's data + + m_loaded_from_file = false; + m_loaded_to_opengl = false; + + m_data_position.clear(); + m_data_normal.clear(); + + m_vbo_id_position = 0; + m_vbo_id_normal = 0; + m_numVertices = 0; + } +} diff --git a/game/renderer_polygon_3d/polygon_model.hpp b/game/renderer_polygon_3d/polygon_model.hpp index a5c1ce6..9b67a9a 100644 --- a/game/renderer_polygon_3d/polygon_model.hpp +++ b/game/renderer_polygon_3d/polygon_model.hpp @@ -10,219 +10,29 @@ #include #include +#include "glclasses.hpp" + +// TODO: hide assimp inside +// and enable/disable +// to use own binary format without assimp for speed/compatibiblity + +// TODO: add lod-options +// TODO: add generate from openscad options if models missing namespace endofthejedi { class PolygonModel { public: - PolygonModel(const std::string &filename) : m_filename(filename) - { - clear(); - } + PolygonModel(const std::string &filename); - void clear() - { - // TODO: delete buffers if there's data + void clear(); - m_loaded_from_file = false; - m_loaded_to_opengl = false; + bool import(); - m_data_position.clear(); - m_data_normal.clear(); - - m_vbo_id_position = 0; - m_vbo_id_normal = 0; - m_numVertices = 0; - } - - bool import() - { - clear(); - - // Create an instance of the Importer class - Assimp::Importer importer; - // And have it read the given file with some example postprocessing - // Usually - if speed is not the most important aspect for you - you'll - // propably to request more postprocessing than we do in this example. - const aiScene* scene = importer.ReadFile(m_filename, - aiProcess_CalcTangentSpace | - aiProcess_Triangulate | - aiProcess_JoinIdenticalVertices | - aiProcess_SortByPType); - - // If the import failed, report it - if (!scene) { - std::cout<<"[polygonmodel] loading file " - << m_filename << " failed with: " - << importer.GetErrorString() << std::endl; - - return false; - } - - // Now we can access the file's contents. - copyVertices(scene); - - m_loaded_from_file = true; - - // We're done. Everything will be cleaned up by the importer destructor - return true; - } - - bool uploadToOpenGl() - { - if (!m_loaded_from_file) { - std::cerr<<"[polygonmodel] warning: try to upload model data " - << "to OpenGL but no data is loaded!" << std::endl; - - exit(-1); - return false; - } - - /************************************************************/ - /* Position data */ - /************************************************************/ - - glEnableVertexAttribArray(0); - - glGenBuffers(1, &m_vbo_id_position); // Generate buffer - glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_position); // Bind buffer - - glVertexAttribPointer(0, - 3, // three floats per vertex - GL_FLOAT, // Data is floating point type - GL_FALSE, // No fixed point scaling - 0, // stride: no - NULL); // No offset - - // fill buffer with the loaded mesh position data - glBufferData( - GL_ARRAY_BUFFER, // Buffer target - 3 * m_numVertices * sizeof(float), // Buffer data size - m_data_position.data(), // Buffer data pointer - GL_STATIC_DRAW); // Usage - Data never changes; - - /************************************************************/ - /* Normal data */ - /************************************************************/ - - glEnableVertexAttribArray(1); - glGenBuffers(1, &m_vbo_id_normal); // Generate buffer - glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_normal); // Bind buffer - - glVertexAttribPointer( - 1, - 3, // three floats per normal - GL_FLOAT, // Data is floating point type - GL_FALSE, // No fixed point scaling - 0, // stride: no - NULL); // No offset - - // Fill bound buffer - glBufferData( - GL_ARRAY_BUFFER, // Buffer target - 3 * m_numVertices * sizeof(float), // Buffer data size - m_data_normal.data(), // Buffer data pointer - GL_STATIC_DRAW); // Usage - Data never changes; - - m_loaded_to_opengl = true; - - return true; - } - - bool bind(Shader &shader) - { - if (!m_loaded_to_opengl) { - std::cout<<"[polygonmodel] warning: try to bind model vbo " - << "which was not uploaded to OpenGL!" << std::endl; - - exit(-1); - return false; - } - - // bind position vbo - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_position); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); - - // bind normal vbo - GLuint loc = glGetAttribLocation(shader.program(), "in_normal"); - glEnableVertexAttribArray(loc); - glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_normal); - glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, NULL); - - m_binding_active = true; - - return true; - } - - bool render(Shader& shader) - { - (void) shader; - - if (!m_binding_active || !m_loaded_to_opengl) { - std::cout<<"[polygonmodel] warning: try to render model without bind()" << std::endl; - exit(-1); - return false; - } - - //GLuint l0 = glGetAttribLocation(shader.program(), "in_normal"); - //GLuint l1 = glGetAttribLocation(shader.program(), "in_vertex"); - //GLuint l2 = glGetAttribLocation(shader.program(), "in_fakkkke"); - //std::cout<<"locations: " << l0 << " " << l1 << " " << l2 << std::endl; - - //glBindAttribLocation(shader.program(), 0, "in_vertex"); - //glBindAttribLocation(shader.program(), 1, "in_normal"); - - glDrawArrays(GL_TRIANGLES, 0, m_numVertices); - return true; - } + bool uploadToOpenGl(); + bool bind(Shader &shader); + bool render(Shader& shader); private: - bool copyVertices(const aiScene *scene) - { - if (scene->mMeshes == 0) { - std::cout << "[polygonmodel : no meshes loaded for " << m_filename << std::endl; - return false; - } - - aiNode *node = scene->mRootNode; - const aiMesh* mesh = scene->mMeshes[node->mMeshes[0]]; - - // 3 vertices per face, 3 floats per vertex - m_numVertices = mesh->mNumFaces*3; - - m_data_position.reserve(m_numVertices); - m_data_normal.reserve(m_numVertices); - - size_t t, i; - for (t=0; tmNumFaces; ++t) { - const aiFace* face = &mesh->mFaces[t]; - if (face->mNumIndices != 3) { - std::cout << "[polygonmodel] need triangles, got something different with: " - << face->mNumIndices << " vertices" << std::endl; - - return false; - } - - for (i=0; imNumIndices; i++) { - const size_t index = face->mIndices[i]; - m_data_position.push_back(mesh->mVertices[index].x); - m_data_position.push_back(mesh->mVertices[index].y); - m_data_position.push_back(mesh->mVertices[index].z); - - m_data_normal.push_back(mesh->mNormals[index].x); - m_data_normal.push_back(mesh->mNormals[index].y); - m_data_normal.push_back(mesh->mNormals[index].z); - - //std::cout<<"adding normal: " << mesh->mNormals[index].x << " " << mesh->mNormals[index].y << " " << mesh->mNormals[index].z << std::endl; - } - } - - size_t totalBytes = 3*m_numVertices*sizeof(float); - std::cout<<"[polygonmodel] loaded file " << m_filename - << " with " << m_numVertices << " vertices (" - << totalBytes << " bytes)" << std::endl; - - return true; - } + bool copyVertices(const aiScene *scene); const std::string &filename() const { return m_filename; } diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.cpp b/game/renderer_polygon_3d/renderer_polygon_3d.cpp index 2c3ffea..949d94d 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.cpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.cpp @@ -61,20 +61,29 @@ namespace endofthejedi { dt = 0.0; } - glClearColor(0.0, 0.0, 0.0, 1.0); - m_state = state; - advanceGraphicObjects(dt); + // TODO: add stars (texture) + // TODO: add dust particles + // TODO: add little rocks flying around + + glClearColor(0.0, 0.0, 0.0, 1.0); + m_shader.bind(); + glm::vec3 c = glm::vec3(1.0, 1.0, 0.5); + glUniform3f(m_shader.location("lightColor"), c.x, c.y, c.z); + + glm::vec3 p = glm::vec3(1.0, 0.0, 0.0); + glUniform3f(m_shader.location("lightPosition"), p.x, p.y, p.z); + renderPlanets(); renderShips(); renderMissiles(); //glDisable(GL_DEPTH_TEST); - renderParticles(); + //renderParticles(); //glEnable(GL_DEPTH_TEST); renderTraces(); @@ -151,7 +160,7 @@ namespace endofthejedi { glUniformMatrix4fv(m_shader.location("model"), 1, GL_FALSE, glm::value_ptr(model)); glm::vec3 c = planet->getColor(); - glUniform3f(m_shader.location("color"), c.x, c.y, c.z); + glUniform3f(m_shader.location("materialColor"), c.x, c.y, c.z); m_planetModel->render(m_shader); } @@ -164,7 +173,7 @@ namespace endofthejedi { for (const game::Player *player : m_state->players) { for (const game::Missile *missile : player->missiles) { glm::vec3 c = glm::vec3(1.0, 1.0, 0.3); - glUniform3f(m_shader.location("color"), c.x, c.y, c.z); + glUniform3f(m_shader.location("materialColor"), c.x, c.y, c.z); glm::mat4 model = computeModelMatrix(missile); glUniformMatrix4fv(m_shader.location("model"), 1, GL_FALSE, glm::value_ptr(model)); @@ -183,7 +192,7 @@ namespace endofthejedi { glUniformMatrix4fv(m_shader.location("model"), 1, GL_FALSE, glm::value_ptr(model)); glm::vec3 c = glm::vec3(0.1, 1.0, 0.2); - glUniform3f(m_shader.location("color"), c.x, c.y, c.z); + glUniform3f(m_shader.location("materialColor"), c.x, c.y, c.z); m_shipModel->render(m_shader); }