ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

openglsprop.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/gfx/openglsprop.h"
00024 
00025 #include "engines/stark/gfx/driver.h"
00026 #include "engines/stark/gfx/texture.h"
00027 #include "engines/stark/formats/biffmesh.h"
00028 #include "engines/stark/scene.h"
00029 #include "engines/stark/services/services.h"
00030 
00031 #include "graphics/opengl/shader.h"
00032 
00033 namespace Stark {
00034 namespace Gfx {
00035 
00036 OpenGLSPropRenderer::OpenGLSPropRenderer(Driver *gfx) :
00037         VisualProp(),
00038         _gfx(gfx),
00039         _faceVBO(0),
00040         _modelIsDirty(true) {
00041     static const char* attributes[] = { "position", "normal", "texcoord", nullptr };
00042     _shader = OpenGL::Shader::fromFiles("stark_prop", attributes);
00043 }
00044 
00045 OpenGLSPropRenderer::~OpenGLSPropRenderer() {
00046     clearVertices();
00047 
00048     delete _shader;
00049 }
00050 
00051 void OpenGLSPropRenderer::render(const Math::Vector3d &position, float direction, const LightEntryArray &lights) {
00052     if (_modelIsDirty) {
00053         // Update the OpenGL Buffer Objects if required
00054         clearVertices();
00055         uploadVertices();
00056         _modelIsDirty = false;
00057     }
00058 
00059     _gfx->set3DMode();
00060 
00061     Math::Matrix4 model = getModelMatrix(position, direction);
00062     Math::Matrix4 view = StarkScene->getViewMatrix();
00063     Math::Matrix4 projection = StarkScene->getProjectionMatrix();
00064 
00065     Math::Matrix4 modelViewMatrix = view * model;
00066     modelViewMatrix.transpose(); // OpenGL expects matrices transposed when compared to ResidualVM's
00067 
00068     Math::Matrix4 projectionMatrix = projection;
00069     projectionMatrix.transpose(); // OpenGL expects matrices transposed when compared to ResidualVM's
00070 
00071     Math::Matrix4 normalMatrix = modelViewMatrix;
00072     normalMatrix.invertAffineOrthonormal();
00073     //normalMatrix.transpose(); // OpenGL expects matrices transposed when compared to ResidualVM's
00074     //normalMatrix.transpose(); // No need to transpose twice in a row
00075 
00076     _shader->enableVertexAttribute("position", _faceVBO, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0);
00077     _shader->enableVertexAttribute("normal", _faceVBO, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 12);
00078     _shader->enableVertexAttribute("texcoord", _faceVBO, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 24);
00079     _shader->use(true);
00080 
00081     _shader->setUniform("modelViewMatrix", modelViewMatrix);
00082     _shader->setUniform("projectionMatrix", projectionMatrix);
00083     _shader->setUniform("normalMatrix", normalMatrix.getRotation());
00084     setLightArrayUniform(lights);
00085 
00086     const Common::Array<Face> &faces = _model->getFaces();
00087     const Common::Array<Material> &materials = _model->getMaterials();
00088 
00089     for (Common::Array<Face>::const_iterator face = faces.begin(); face != faces.end(); ++face) {
00090         const Material &material = materials[face->materialId];
00091 
00092         // For each face draw its vertices from the VBO, indexed by the EBO
00093         const Gfx::Texture *tex = _texture->getTexture(material.texture);
00094         if (tex) {
00095             tex->bind();
00096         } else {
00097             glBindTexture(GL_TEXTURE_2D, 0);
00098         }
00099 
00100         _shader->setUniform("textured", tex != nullptr);
00101         _shader->setUniform("color", Math::Vector3d(material.r, material.g, material.b));
00102         _shader->setUniform("doubleSided", material.doubleSided ? 1 : 0);
00103 
00104         GLuint ebo = _faceEBO[face];
00105         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
00106         glDrawElements(GL_TRIANGLES, face->vertexIndices.size(), GL_UNSIGNED_INT, 0);
00107     }
00108 
00109     _shader->unbind();
00110 }
00111 
00112 void OpenGLSPropRenderer::clearVertices() {
00113     OpenGL::Shader::freeBuffer(_faceVBO);
00114 
00115     for (FaceBufferMap::iterator it = _faceEBO.begin(); it != _faceEBO.end(); ++it) {
00116         OpenGL::Shader::freeBuffer(it->_value);
00117     }
00118 
00119     _faceEBO.clear();
00120 }
00121 
00122 void OpenGLSPropRenderer::uploadVertices() {
00123     _faceVBO = createFaceVBO();
00124 
00125     const Common::Array<Face> &faces = _model->getFaces();
00126     for (Common::Array<Face>::const_iterator face = faces.begin(); face != faces.end(); ++face) {
00127         _faceEBO[face] = createFaceEBO(face);
00128     }
00129 }
00130 
00131 GLuint OpenGLSPropRenderer::createFaceVBO() {
00132     const Common::Array<Formats::BiffMesh::Vertex> &vertices = _model->getVertices();
00133 
00134     return OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(float) * 9 * vertices.size(), &vertices.front());
00135 }
00136 
00137 GLuint OpenGLSPropRenderer::createFaceEBO(const Face *face) {
00138     return OpenGL::Shader::createBuffer(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32) * face->vertexIndices.size(), &face->vertexIndices.front());
00139 }
00140 
00141 void OpenGLSPropRenderer::setLightArrayUniform(const LightEntryArray &lights) {
00142     static const uint maxLights = 10;
00143 
00144     assert(lights.size() >= 1);
00145     assert(lights.size() <= maxLights);
00146 
00147     const LightEntry *ambient = lights[0];
00148     assert(ambient->type == LightEntry::kAmbient); // The first light must be the ambient light
00149     _shader->setUniform("ambientColor", ambient->color);
00150 
00151     Math::Matrix4 viewMatrix = StarkScene->getViewMatrix();
00152     Math::Matrix3 viewMatrixRot = viewMatrix.getRotation();
00153 
00154     for (uint i = 0; i < lights.size() - 1; i++) {
00155         const LightEntry *l = lights[i + 1];
00156 
00157         Math::Vector4d worldPosition;
00158         worldPosition.x() = l->position.x();
00159         worldPosition.y() = l->position.y();
00160         worldPosition.z() = l->position.z();
00161         worldPosition.w() = 1.0;
00162 
00163         Math::Vector4d eyePosition = viewMatrix * worldPosition;
00164 
00165         // The light type is stored in the w coordinate of the position to save an uniform slot
00166         eyePosition.w() = l->type;
00167 
00168         Math::Vector3d worldDirection = l->direction;
00169         Math::Vector3d eyeDirection = viewMatrixRot * worldDirection;
00170         eyeDirection.normalize();
00171 
00172         _shader->setUniform(Common::String::format("lights[%d].position", i).c_str(), eyePosition);
00173         _shader->setUniform(Common::String::format("lights[%d].direction", i).c_str(), eyeDirection);
00174         _shader->setUniform(Common::String::format("lights[%d].color", i).c_str(), l->color);
00175 
00176         Math::Vector4d params;
00177         params.x() = l->falloffNear;
00178         params.y() = l->falloffFar;
00179         params.z() = l->innerConeAngle.getCosine();
00180         params.w() = l->outerConeAngle.getCosine();
00181 
00182         _shader->setUniform(Common::String::format("lights[%d].params", i).c_str(), params);
00183     }
00184 
00185     for (uint i = lights.size() - 1; i < maxLights; i++) {
00186         // Make sure unused lights are disabled
00187         _shader->setUniform(Common::String::format("lights[%d].position", i).c_str(), Math::Vector4d());
00188     }
00189 }
00190 
00191 } // End of namespace Gfx
00192 } // End of namespace Stark


Generated on Sat May 25 2019 05:00:50 for ResidualVM by doxygen 1.7.1
curved edge   curved edge