imt2531-assignment2

所属分类:代码编辑器
开发工具:C
文件大小:9715KB
下载次数:0
上传日期:2018-04-30 17:56:55
上 传 者sh-1993
说明:  图形编程的第二个项目-OpenGL三维对象查看器编辑器
(Second project in graphics programming - An OpenGL 3D Object viewer editor)

文件列表:
CMakeLists.txt (4736, 2018-05-01)
CMakeSettings.json (1089, 2018-05-01)
CppProperties.json (1368, 2018-05-01)
assets (0, 2018-05-01)
assets\materials (0, 2018-05-01)
assets\materials\_default.yml (172, 2018-05-01)
assets\materials\brick.yml (139, 2018-05-01)
assets\materials\skybox.yml (59, 2018-05-01)
assets\materials\spaceSkybox.yml (60, 2018-05-01)
assets\materials\subsurfaceScatter.yml (136, 2018-05-01)
assets\models (0, 2018-05-01)
assets\models\Icosphere.yml (4800, 2018-05-01)
assets\models\Suzanne.yml (59673, 2018-05-01)
assets\models\_default.yml (158494, 2018-05-01)
assets\models\cube.yml (2317, 2018-05-01)
assets\models\skybox.yml (1315, 2018-05-01)
assets\models\spaceSkybox.yml (1320, 2018-05-01)
assets\scenes (0, 2018-05-01)
assets\scenes\_default.yml (735, 2018-05-01)
assets\scenes\demo1.yml (5719, 2018-05-01)
assets\scenes\skybox.yml (970, 2018-05-01)
assets\shaders (0, 2018-05-01)
assets\shaders\_default.glsl (743, 2018-05-01)
assets\shaders\base.glsl (5285, 2018-05-01)
assets\shaders\skybox.glsl (872, 2018-05-01)
assets\shaders\subsurfaceScatter.glsl (5038, 2018-05-01)
assets\textures (0, 2018-05-01)
assets\textures\_default.jpg (128266, 2018-05-01)
assets\textures\brickwall-nrm.jpg (547257, 2018-05-01)
assets\textures\brickwall.jpg (178219, 2018-05-01)
assets\textures\example.jpg (33321, 2018-05-01)
assets\textures\example_nrm.jpg (93470, 2018-05-01)
assets\textures\nrm_test.jpg (38358, 2018-05-01)
assets\textures\scifi.jpg (113159, 2018-05-01)
... ...

[TOC] # Curiosity task - 3D object viewer We are not doing Pacman. Instead we are doing a Curiousity Task. We are focusing heavily on Architecture/Framework development for an OpenGL graphics engine. The goal of our engine is to provide a 3D viewer with loading of resource files during run-time. The 3D-viewer will support 5 different files which may be loaded, edited, re-loaded during run-time by the user: - Texture files (e.g. brickwall.jpg) - Shader files (e.g. base.glsl) - Material files (e.g. brickwall.yml - custom format) - Model files (e.g. cube.yml - custom format) - Scene files (e.g. playground.yml - custom format) We are focusing on beiing as generic as possible when supporting these files, to empower the user. We are trying to make it possible for non-programmers to enjoy the 3D-viewer, although the text-only input system might scare some people away. Our target user is an educator or a student who wants to learn about 3D graphics datastructures and systems. To make our custom model format usable, we want to write an exporter for Blender for exporting models, i.e. their vertex- and face informaion (position, normal, uv coordinates ...) to our custom format. We want to model an entire scene graph. # Install Instructions ## Windows 1. Adding the CMake-module for Visual Studio: - Install Visual Studio 2017 15.4 or newer (the CMake module is only available for these versions). - From Visual Studio: go to `Tools->Get Tools And Features...` - Select the box named `Desktop development with C++` - Enable the checkbox named `Visual C++ Tools for CMake` in the righthand column - Press `Modify` to apply the module 2. Install [python 3](https://www.python.org/downloads/)(or newer) - Make sure the installation directory is `C:\tools\Python36\python.exe` 3. Clone [the repository](http://prod3.imt.hig.no/overkill-studios/imt2531-assignment2) - from gitbash: `> cd "./yourdesiredworkdir/"` - from gitbash: `> git clone http://prod3.imt.hig.no/overkill-studios/imt2531-assignment2.git` 4. In Visual Studio: go to `File->Open->CMake...`, and select the CMakeLists.txt file located in `./yourdesiredworkdir/imt2531-assignment2/` # Controls ``` Reload shaders - 1 Reload materials - 2 Reload models - 3 Reload scene - 4 Move camera: Forwards - W Left - A Backwards - S Right - D Down - Q Up - E Rotate camera: Pitch - Mouse up/down Yaw - Mouse left/right Switch camera - Tab Switch camera mode - Space ``` ##### Additional/Optional setup - Running the program with different scenes: To start the program from a differet scene all you need to do is specify another configuration in the file named `launch.vs.json`, this can be found in the hidden directory `.vs`, or by going to `CMake->Debug and Launch Settings`. Setting the args of a configuration to reflect a scene will make that scene open upon building & debugging with said configuration. ## MacOS ## Linux Since we are using c++17 features, a newer compiler is necessary. We are also using python3 or above. ```bash # Install Clang++ 5 (allowing c++17 features to be compiled) sudo apt-get install clang++-5.0 # Install python3 (NOTE: a lot of ubuntu distros already come with this) sudo apt-get install python3.5 #Remove previous installations of cmake sudo apt-get remove --purge cmake mkdir ~/temp # make a temp folder for the cmake binaries cd ~/temp wget https://cmake.org/files/v3.11/cmake-3.11.0-Linux-x86_***.tar.gz # unzip the binaries tar -xzvf cmake-3.11.0-Linux-x86_***.tar.gz cd ~/temp/cmake-3.11.0-Linux-x86_***/ #place the binaries cp -r ./bin /usr/ cp -r ./doc /usr/share/ cp -r ./man /usr/share/ cp -r ./share /usr/ cmake --version # verify the new installation: # expected: cmake version 3.11.0 rm -r ~/temp # cleanup temp directory, it's no longer needed git clone http://prod3.imt.hig.no/overkill-studios/imt2531-assignment2.git cd imt2531-assignment2 mkdir build cd build cmake .. -DCMAKE_CXX_COMPILER=clang++-5.0 make ./cube ./cube assets/scenes/demo1.yml # Load specific scene. ``` # Roadmap ## Minimum Requirements assignment 2 - [x] Textured walls floors - [ ] Menu for pause, resume and exit. (we were excused for this point as it didn't fit the kind of program we made) - [x] Move objects/camera using keyboard or mouse. - [x] Load at least 1 model from a model file. (custom format) - [x] Basic lighting model ## Optional requirement assignment 2 - [x] Advanced lighting/reflection materials - [x] Change perspective - [x] Use of multiple advanced mesh. - [x] Write own object loader - [x] Make Camera movable - [x] Multiple scenes ## Own requirements Engine - [x] Render a cube.
- [x] Add texture to the cube
- [x] Make the cube spin.
- [x] Add material to the cube.
- [x] Use 2 materials on different parts of the cube.
- [x] Move the cube using mouse input.
- [x] Add floor.
- [x] Texturize the floor.
- [x] Toggle camera spin around the cube.
- [x] Toggle ambient light. Scale ambient light up down.
- [x] Add a directional light.
- [x] Implement Phong lighting model using cube vertex normals.
- [x] Render cube with specular map.
- [ ] Add one of the simple shadow models.
- [x] Swap between 2 different shaders at run-time.
- [x] Swap between 2 different cube materials at run-time.
- [x] Render 2 cubes side by side with different materials.
- [x] Repeat the above with model of the teapot.
## Extra File loader - [x] Load a Shader. (vertex & geometry & fragment)
- [x] Load a Texture. (diffuse & specular)
- [x] Load a Vertexbuffer
- [x] Load a Mesh with indicies to that vertexbuffer.
- [x] Load a Material.
- [x] Load a Transform.
- [x] Load an Entity { Mesh, Material, Transform }
- [x] Render that loaded Entity.
- [x] Update render of loaded Entity on file change
# Extended feature list ## 1. Rendering of 3D models. 3D models are rendered in a GLFW window. Rendering 3D models in it's simplest form is just pushing each individual vertex down the 3D rendering pipeline of the GPU using shaders. In OpenGL this is achieved by writing -> loading -> compiling -> linking -> buffering -> binding and running the following shader minimum. ```c= #shader vertex #version 150 in vec4 position; in vec4 color; out vec4 color_from_vshader; void main() { gl_Position = position; color_from_vshader = color; } #shader fragment #version 150 in vec4 color_from_vshader; out vec4 out_color; void main() { out_color = color_from_vshader; } ``` We expanded quite a bit more than just rendering 3D models. Some of the features you will find in our shaders are: * Texture mapping * Bump mapping (normal mapping) * Ambient lighting * Diffuse lighting * Specular lighting * Subsurface scattering ## 2. Loading of 3D models from custom simplified format. The costum file format in yaml that consists of a vertex count, then a list of vertecies where each define a point in space, its normal vector, its UV coordintes and lastly color.
```yaml vertices: 1560 # x y z nx ny nz u v r g b a v: 1.24 0.65 0.10 -0.85 -0.52 0.00 0.0 0.0 255 255 255 150 v: 1.27 0.67 0.10 ...... v: 1.30 0.60 0.10 ....... ... ``` Then a mesh count, describing how many meshes are to come.
Each mesh has its name, material, shader and count of how many triangles it consists of. Each triangle lists three vertex indecies to define it. ```yaml meshes: 1 mesh: blendermesh material: _default shader: _default triangles: 1166 t: *** 92 65 t: 92 66 65 t: 92 0 66 ``` ## 3. Python script for blender, to export to custom model format. Since we had our own model format, we needed a way to bring in models. Using Blender for this was a good choice. It supports almost any model format. The only thing we need is an exporter from Blender. Blender is also an excellent tool for just fixing stuff related to models. Triangulation, scaling, rotation. Blender is scripted using Python. The Python script can be executed inside blenders text-editor. ```python= import bpy active_object = bpy.context.active_object ``` By reading the data stored in the `bpy.context` we can pull out almost anything. A comprehensive documentation of the Blender Python API can be found here https://docs.blender.org/api/2.79/ - 30.04.2018 Blender also has a python console for easy testing ![Imgur](https://i.imgur.com/8AUWTTo.png) ## 4. Transorms, complete with position, rotation, scale, velocity,angular velocity, and children. Entities in the framework have a tag(string) that is unique, with a corresponing id(int) that is equally unique. The reason is that int are much faster to address by during runtime. However strings are much more readable.
The entity uses 6 glm vector3s to keep track of its position, rotation, scale, velocity and angular velocity. These vectors are in model space, if the entiry is root in the world, that vector is in the world's model space, more commonly refered to as world space. Hovever if it is child of another entity, the position is relative to it's parent's.
Each entity also has a list of entity ids that describe which other entities in the world that are children of the entity. When the entity updates, the model matrix is passed to each of the children. ## 5. Shader programs combined in single files. Parsed during runtime. Our shader program parser reads entire shaderprograms written as a single file with the directives `#shader vertex | geometry | fragment` marking the start of different shaders. This allows users to more clearly see the flow of input/output between shaders. ## 6. Additional syntax for shaders As mentioned above, we've added custom directives for the parser to handle. in addition to the `#shader` directive, we've added the `#prop` directive. The `#prop` directive is used for setting program specific draw properties. The draw properties we allow to change through this directive are: - Culling `#prop Cull {{on | off} | {back | front | both}}` - Depth Test `#prop ZTest {on | off}` - Blend Function `#prop Blend {{on | off} | }` where A and B may be one of the following (see [OpenGL blending](https://www.khronos.org/opengl/wiki/Blending) for further explanation): ``` OneMinusConstantAlpha, OneMinusConstantColor, OneMinusDstAlpha, OneMinusSrcColor, OneMinusDstColor, OneMinusSrcAlpha, SrcAlphaSaturate, ConstantColor, ConstantAlpha Zero, One, SrcColor, DstColor, SrcAlpha, DstAlpha ``` for readability the parser allows the following negative values: `off | false | 0 | disabled` and positive values: `on | true | 1 | enabled` (or for that matter anything else that is not considered negative) if these directives are not used, the program will default to the following: ``` Cullface: Back BlendFunc: SrcAlpha, OneMinusDstAlpha DepthTest: On ``` These directives allow shader programs to take control of the way they are rendered by the renderer by swapping the state of said properties on just before anything is drawn (i.e. on binding), and disabling them as soon as the drawcall is done. ## 7. Material files coupled with shaders that are attached to models. Transformable enity. yaml ## 8. Point lights. Transformable entity. ## 9. Directional light. Transformable entity(only rotation and angular velocity). ## 10. Cameras using perspective projection There can be several cameras in the scene. You can switch between them using TAB. There are also two camera modes, FREELOOK and ORBITAL, which you switch between using SPACE. ```cpp enum CameraMode { FREELOOK, ORBITAL }; ``` The freelook mode is like the noclip mode first person shooter often have when spectating a game. You can look around with the mouse, and move in whatever direction you're pointing(using WASD-QE). Orbital mode is similar to freelook. However, when moving the mouse, the camera will orbit around origin of the camera's parent. If the camera is root that's 0,0,0 world space. Implementing a third camera mode would be pretty painless as the structure of the camera is set up to support several. It would be as simpe as adding an enum entry, and two switch cases, all in the same class. ## 11. Loading of scene files that defines the layout of cameras, models, directional light, and pointlights. The scene file consists of cameras, entities(models, and empty nodes), point lights, directional light, and child-parent relations. The file starts with a camera count, then the camera entities. Each camera entity has it's tag, position, rotation, velocity and angular velocity. Followed by the camera mode, nearclip and lastly farclip. Then entity count. An entity has it's unique entity tag, a model tag that is unique per model, position, roation, scale, velocity and it's angular velocity. Then point light count, then the point light entites. Each point light has an entity tag, it's position, velocity, it's vec3 of light intensities which determine it's color, lastly it's cev ## 12. Robust feedback Somewhat good error feedback - - **For shader errors**: we're using program introspection to get linking status which in turn allows us to direct users to potential issues in their shader code. We print information about which shader is unable to attatch/link (vertex/fragment/geometry), and the line in the shaderprogram file in which the error occurs. Additionally an error-shader is used, clearly indicating to the user that something went wrong. - **For model errors**: if you're trying to use a non-existing model in a scene, the application will instead plug in an error-model where the model should've appeared. - **For material errors**: if you're trying to use a non-existing material on a model, the application will instead use an error-material. This material applies _crazy_ values to uniforms to try to make the shader program result as _wrong_ as possible, indicating that something is wrong. All of the above cases will be logged to the console, allowing the user to inspect exactly what went wrong when loading. ## 13. Child-parent relationship between entities where children inherit their parent's transormation. ```yaml relations: 24 sun: 0 mercury: 0 mercuryCore: 1 mercury venusCam: 0 venus: 1 venusCam venusCore: 1 venus earthCam: 0 moonMoonCam: 0 moon2: 0 moonCore2: 1 moon2 moon: 2 moonCore2 moonMoonCam moonCore: 1 moon # Many more relations.... ``` # Future work / Discussion ## 1. Split up \.yml files into \.yml and \.yml files ### How do we do it now? Currently in our model-files we are specifying which shader and material are to be used in the rendering of our models. This has created a strong coupling of a mesh to the shader and material. Stronger than we would like. I will mention two big problems with this: 1. It is not convenient to go inside the model file, in between all the vertices and triangle to edit the materials and shaders attached to that model. 2. For every new model with the same vertices, but with different materials, we have to duplicate all the vertices and indicies. This does not make sense for a big model. Loading times will get out of hand quickly. *model/human.yml* ```yml vertices: 1560 v: 1.138500 0.5***000 -0.100000 0.707 -0.707 0.000 0.000 0.000 255 255 255 255 v: 1.138500 0.5***000 0.100000 0.707 -0.707 0.000 0.000 0.000 255 255 255 255 v: 1.138500 0.384000 -0.100000 0.707 0.707 0.000 0.000 0.000 255 255 255 255 v: 1.138500 0.384000 0.100000 0.707 0.707 0.000 0.000 0.000 255 255 255 255 .... 1000's more vertices meshes: 1 mesh: blendermesh material: _default # < -- Awkward to have to go here to edit material here in between 1000's of lines of data. shader: _default triangles: 1166 t: *** 92 65 t: 92 66 65 t: 92 0 66 t: 92 1 0 t: 92 2 1 t: 92 3 2 t: 92 4 3 t: 92 5 4 .... 1000's more triangles ``` *scene/demo.yml* ```yml entities: 1 entity: player1 model: human position: 10 0 0 rotation: 0 0 -90 # ...and so on ``` ### What could be a better approach? An intermediate format representing a `prefab` would have been nice. A prefab would then stich everything together. An entity would be an instance of a prefab. *mesh/right-arm.yml* ```yml vertices: 1560 v: 1.138500 0.5***000 -0.100000 0.707 -0.707 0.000 0.000 0.000 255 255 255 255 v: 1.138500 0.5***000 0.100000 0.707 -0.707 0.000 0.000 0.000 255 255 255 255 v: 1.138500 0.384000 -0.100000 0.707 0.707 0.000 0.000 0.000 255 255 255 255 v: 1.138500 0.384000 0.100000 0.707 0.707 0.000 0.000 0.000 255 255 255 255 #.... 1000's more vertices triangles: 1166 t: *** 92 65 t: 92 66 65 t: 92 0 66 t: 92 1 0 t: 92 2 1 t: 92 3 2 t: 92 4 3 t: 92 5 4 #.... 1000's more triangles ``` *prefab/human.yml* ```yml meshes: 4 mesh: right-arm shader: basic-color material: red mesh: left-arm shader: basic-color material: blue mesh: head shader: mat-texture material: _default mesh: foot shader: mat-texture material: brick ``` *scene/demo.yml* ```yml entities: 1 entity: player1 prefab: human position: 10 0 0 rotation: 0 0 -90 # ...and so on ``` ## 2. Watch files and reload on modify Currently systems in our 3D engine reloads ALL files every time the users asks for an update. If a shader is edited, the user click `KEY_1` and all shaders are reloaded and compiled. After using our system, we see that it would be better to just update the single file a users saves changes to. This should also just happen automatically. I file watcher would signal the engine of which file it should reload/recompile. An attempt was made to actually implement this in our project but we did not succeed finding a good solution within fair time. A few solutions was explored ### std::filessystem (c++17 library) This is a really good candidate for solving this issue. The problem is that very few compilers have support for this library as of april 2018. It would be awesome to just include a standard library. *std::filesystem* - http://en.cppreference.com/w/cpp/filesystem - 30.04.2018 ### boost::filesystem from the C++ boost library The boost::filesystem is the inspiration for std::filesystem, and is currently in a much more stable state. The BIG drawback is that it require installation of the boost library, which is not a trivial thing to have as a dependency. The library in itself is huge, and is not easy pick specific modules. The size of the library is around 2.3 GB on windows. I could not succeed installing the library on windows. *boost* - https://www.boost.org/doc/libs/1_67_0/libs/filesystem/doc/index.htm - 30.04.2018 ### Using stat(2) unix - get file status Unix stat is in theory supported on all 3 major platforms(linux, windows an ... ...

近期下载者

相关文件


收藏者