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

graphics/opengl/surfacerenderer.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 "common/scummsys.h"
00024 
00025 #if defined(USE_OPENGL)
00026 
00027 #include "graphics/opengl/surfacerenderer.h"
00028 
00029 #include "graphics/opengl/context.h"
00030 #include "graphics/opengl/texture.h"
00031 
00032 #if defined(USE_OPENGL_SHADERS) || defined(USE_GLES2)
00033 #include "graphics/opengl/shader.h"
00034 #endif
00035 
00036 namespace OpenGL {
00037 
00038 SurfaceRenderer *createBestSurfaceRenderer() {
00039 #if defined(USE_OPENGL_SHADERS) || defined(USE_GLES2)
00040     if (OpenGLContext.shadersSupported) {
00041         return new ShaderSurfaceRenderer();
00042     }
00043 #endif
00044 
00045 #ifndef USE_GLES2
00046     return new FixedSurfaceRenderer();
00047 #else
00048     error("Could not create an appropriate surface renderer for the current OpenGL context");
00049 #endif
00050 }
00051 
00052 SurfaceRenderer::SurfaceRenderer() :
00053         _flipY(false),
00054         _alphaBlending(false) {
00055 }
00056 
00057 SurfaceRenderer::~SurfaceRenderer() {
00058 }
00059 
00060 void SurfaceRenderer::setFlipY(bool flipY) {
00061     _flipY = flipY;
00062 }
00063 
00064 void SurfaceRenderer::enableAlphaBlending(bool enable) {
00065     if (_alphaBlending != enable) {
00066         glEnable(GL_BLEND);
00067         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00068     } else {
00069         glDisable(GL_BLEND);
00070     }
00071     _alphaBlending = enable;
00072 }
00073 
00074 #ifndef USE_GLES2
00075 
00076 FixedSurfaceRenderer::~FixedSurfaceRenderer() {
00077 }
00078 
00079 void FixedSurfaceRenderer::prepareState() {
00080     // Save current state
00081     glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
00082 
00083     // prepare view
00084     glMatrixMode(GL_PROJECTION);
00085     glPushMatrix();
00086     glLoadIdentity();
00087     glOrtho(0, 1.0, 1.0, 0, 0, 1);
00088 
00089     glMatrixMode(GL_MODELVIEW);
00090     glPushMatrix();
00091     glLoadIdentity();
00092 
00093     glMatrixMode(GL_TEXTURE);
00094     glPushMatrix();
00095     glLoadIdentity();
00096 
00097     glDisable(GL_LIGHTING);
00098     glEnable(GL_TEXTURE_2D);
00099     glDisable(GL_DEPTH_TEST);
00100     glDisable(GL_ALPHA_TEST);
00101     glDepthMask(GL_FALSE);
00102 }
00103 
00104 void FixedSurfaceRenderer::render(const Texture *tex, const Math::Rect2d &dest) {
00105     float texcropX = tex->getWidth() / float(tex->getTexWidth());
00106     float texcropY = tex->getHeight() / float(tex->getTexHeight());
00107     float texTop    = _flipY ? 0.0f : texcropY;
00108     float texBottom = _flipY ? texcropY : 0.0f;
00109 
00110     float offsetX = dest.getTopLeft().getX();
00111     float offsetY = _flipY ? dest.getTopLeft().getY() : 1.0f - dest.getTopLeft().getY() - dest.getHeight();
00112     float sizeX   = fabsf(dest.getWidth());
00113     float sizeY   = fabsf(dest.getHeight());
00114 
00115     glColor4f(1.0, 1.0, 1.0, 1.0);
00116 
00117     glBindTexture(GL_TEXTURE_2D, tex->getTextureName());
00118     glBegin(GL_QUADS);
00119         glTexCoord2f(0, texTop);
00120         glVertex2f(offsetX, offsetY);
00121         glTexCoord2f(texcropX, texTop);
00122         glVertex2f(offsetX + sizeX, offsetY);
00123         glTexCoord2f(texcropX, texBottom);
00124         glVertex2f(offsetX + sizeX, offsetY + sizeY);
00125         glTexCoord2f(0.0, texBottom);
00126         glVertex2f(offsetX, offsetY + sizeY);
00127     glEnd();
00128 }
00129 
00130 void FixedSurfaceRenderer::restorePreviousState() {
00131     glMatrixMode(GL_PROJECTION);
00132     glPopMatrix();
00133 
00134     glMatrixMode(GL_MODELVIEW);
00135     glPopMatrix();
00136 
00137     glMatrixMode(GL_TEXTURE);
00138     glPopMatrix();
00139 
00140     glPopAttrib();
00141 
00142     _flipY = false;
00143     _alphaBlending = false;
00144 }
00145 
00146 #endif
00147 
00148 #if defined(USE_OPENGL_SHADERS) || defined(USE_GLES2)
00149 
00150 ShaderSurfaceRenderer::ShaderSurfaceRenderer() {
00151     const GLfloat vertices[] = {
00152             0.0, 0.0,
00153             1.0, 0.0,
00154             0.0, 1.0,
00155             1.0, 1.0,
00156     };
00157 
00158     // Setup the box shader used to render the overlay
00159     const char *attributes[] = { "position", "texcoord", nullptr };
00160     _boxShader = Shader::fromStrings("box", BuiltinShaders::boxVertex, BuiltinShaders::boxFragment, attributes);
00161     _boxVerticesVBO = Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(vertices), vertices);
00162     _boxShader->enableVertexAttribute("position", _boxVerticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
00163     _boxShader->enableVertexAttribute("texcoord", _boxVerticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
00164 }
00165 
00166 void ShaderSurfaceRenderer::prepareState() {
00167     _boxShader->use();
00168 
00169     glDisable(GL_DEPTH_TEST);
00170     glDepthMask(GL_FALSE);
00171 }
00172 
00173 void ShaderSurfaceRenderer::render(const Texture *tex, const Math::Rect2d &dest) {
00174     glBindTexture(GL_TEXTURE_2D, tex->getTextureName());
00175 
00176     float texcropX = tex->getWidth() / float(tex->getTexWidth());
00177     float texcropY = tex->getHeight() / float(tex->getTexHeight());
00178     _boxShader->setUniform("texcrop", Math::Vector2d(texcropX, texcropY));
00179     _boxShader->setUniform("flipY", _flipY);
00180 
00181     _boxShader->setUniform("offsetXY", dest.getTopLeft());
00182     _boxShader->setUniform("sizeWH", Math::Vector2d(fabsf(dest.getWidth()), fabsf(dest.getHeight())));
00183 
00184     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00185     glBindTexture(GL_TEXTURE_2D, 0);
00186 }
00187 
00188 void ShaderSurfaceRenderer::restorePreviousState() {
00189     glEnable(GL_DEPTH_TEST);
00190     glDepthMask(GL_TRUE);
00191 
00192     _flipY = false;
00193     if (_alphaBlending) {
00194         enableAlphaBlending(false);
00195     }
00196 
00197     _boxShader->unbind();
00198 }
00199 
00200 ShaderSurfaceRenderer::~ShaderSurfaceRenderer() {
00201     Shader::freeBuffer(_boxVerticesVBO);
00202 
00203     delete _boxShader;
00204 }
00205 
00206 #endif
00207 
00208 } // End of namespace OpenGL
00209 
00210 #endif


Generated on Sat Mar 23 2019 05:02:15 for ResidualVM by doxygen 1.7.1
curved edge   curved edge