2021-12-26 21:19:38 +01:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
2020-05-29 13:11:53 +02:00
|
|
|
*
|
2021-12-26 21:19:38 +01:00
|
|
|
* ScummVM is the legal property of its developers, whose names
|
2020-05-29 13:11:53 +02:00
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
2021-12-26 18:47:58 +01:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
2020-05-29 13:11:53 +02:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2021-12-26 21:19:38 +01:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2020-05-29 13:11:53 +02:00
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2021-12-26 18:47:58 +01:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2020-05-29 13:11:53 +02:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2020-08-02 00:44:16 +02:00
|
|
|
#include "engines/wintermute/ad/ad_block.h"
|
|
|
|
#include "engines/wintermute/ad/ad_generic.h"
|
|
|
|
#include "engines/wintermute/ad/ad_walkplane.h"
|
2020-07-06 23:52:19 +02:00
|
|
|
#include "engines/wintermute/base/base_game.h"
|
2020-10-06 07:33:01 +02:00
|
|
|
#include "engines/wintermute/base/gfx/3ds/camera3d.h"
|
|
|
|
#include "engines/wintermute/base/gfx/3ds/light3d.h"
|
2021-12-30 13:49:35 +01:00
|
|
|
|
2020-10-06 07:33:01 +02:00
|
|
|
#include "graphics/opengl/system_headers.h"
|
2021-12-30 13:49:35 +01:00
|
|
|
|
2022-07-13 22:26:29 +02:00
|
|
|
#include "common/config-manager.h"
|
|
|
|
|
2020-10-06 07:33:01 +02:00
|
|
|
#include "math/glmath.h"
|
|
|
|
|
2021-11-17 23:56:21 +00:00
|
|
|
#if defined(USE_OPENGL_GAME)
|
2020-10-06 07:33:01 +02:00
|
|
|
|
2020-06-02 13:42:48 +02:00
|
|
|
#include "engines/wintermute/base/gfx/opengl/base_render_opengl3d.h"
|
|
|
|
#include "engines/wintermute/base/gfx/opengl/base_surface_opengl3d.h"
|
2020-07-21 04:14:33 +02:00
|
|
|
#include "engines/wintermute/base/gfx/opengl/mesh3ds_opengl.h"
|
|
|
|
#include "engines/wintermute/base/gfx/opengl/meshx_opengl.h"
|
2020-07-29 22:54:08 +02:00
|
|
|
#include "engines/wintermute/base/gfx/opengl/shadow_volume_opengl.h"
|
2020-05-19 16:23:53 +02:00
|
|
|
|
2020-05-19 18:30:52 +02:00
|
|
|
namespace Wintermute {
|
2020-07-21 04:14:33 +02:00
|
|
|
BaseRenderer3D *makeOpenGL3DRenderer(BaseGame *inGame) {
|
2020-05-19 18:30:52 +02:00
|
|
|
return new BaseRenderOpenGL3D(inGame);
|
|
|
|
}
|
|
|
|
|
2021-12-30 13:49:35 +01:00
|
|
|
BaseRenderOpenGL3D::BaseRenderOpenGL3D(BaseGame *inGame) : BaseRenderer3D(inGame),
|
|
|
|
_spriteBatchMode(false) {
|
2020-07-06 23:52:19 +02:00
|
|
|
setDefaultAmbientLightColor();
|
2020-08-14 16:38:17 +02:00
|
|
|
|
|
|
|
_lightPositions.resize(maximumLightsCount());
|
|
|
|
_lightDirections.resize(maximumLightsCount());
|
2020-09-20 22:18:55 +02:00
|
|
|
(void)_spriteBatchMode; // silence warning
|
2020-05-19 18:30:52 +02:00
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
BaseRenderOpenGL3D::~BaseRenderOpenGL3D() {
|
2020-05-19 16:23:53 +02:00
|
|
|
}
|
|
|
|
|
2020-08-01 15:48:04 +02:00
|
|
|
void BaseRenderOpenGL3D::setSpriteBlendMode(Graphics::TSpriteBlendMode blendMode) {
|
|
|
|
switch (blendMode) {
|
|
|
|
case Graphics::BLEND_NORMAL:
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
break;
|
2020-06-02 18:52:06 +02:00
|
|
|
|
2020-08-01 15:48:04 +02:00
|
|
|
case Graphics::BLEND_ADDITIVE:
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Graphics::BLEND_SUBTRACTIVE:
|
|
|
|
// wme3d takes the color value here
|
|
|
|
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2020-08-18 21:47:55 +02:00
|
|
|
warning("BaseRenderOpenGL3D::setSpriteBlendMode unsupported blend mode %i", blendMode);
|
2020-08-01 15:48:04 +02:00
|
|
|
}
|
2020-06-02 18:52:06 +02:00
|
|
|
}
|
|
|
|
|
2020-07-06 23:52:19 +02:00
|
|
|
void BaseRenderOpenGL3D::setAmbientLight() {
|
|
|
|
byte a = 0;
|
|
|
|
byte r = 0;
|
|
|
|
byte g = 0;
|
|
|
|
byte b = 0;
|
|
|
|
|
|
|
|
if (_overrideAmbientLightColor) {
|
|
|
|
a = RGBCOLGetA(_ambientLightColor);
|
|
|
|
r = RGBCOLGetR(_ambientLightColor);
|
|
|
|
g = RGBCOLGetG(_ambientLightColor);
|
|
|
|
b = RGBCOLGetB(_ambientLightColor);
|
|
|
|
} else {
|
|
|
|
uint32 color = _gameRef->getAmbientLightColor();
|
|
|
|
|
|
|
|
a = RGBCOLGetA(color);
|
|
|
|
r = RGBCOLGetR(color);
|
|
|
|
g = RGBCOLGetG(color);
|
|
|
|
b = RGBCOLGetB(color);
|
|
|
|
}
|
|
|
|
|
|
|
|
float value[] = { r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f };
|
|
|
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, value);
|
|
|
|
}
|
|
|
|
|
2020-07-06 16:28:01 +02:00
|
|
|
int BaseRenderOpenGL3D::maximumLightsCount() {
|
|
|
|
GLint maxLightCount = 0;
|
|
|
|
glGetIntegerv(GL_MAX_LIGHTS, &maxLightCount);
|
|
|
|
return maxLightCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BaseRenderOpenGL3D::enableLight(int index) {
|
|
|
|
glEnable(GL_LIGHT0 + index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BaseRenderOpenGL3D::disableLight(int index) {
|
|
|
|
glDisable(GL_LIGHT0 + index);
|
|
|
|
}
|
|
|
|
|
2020-07-31 21:16:38 +02:00
|
|
|
void BaseRenderOpenGL3D::setLightParameters(int index, const Math::Vector3d &position, const Math::Vector3d &direction, const Math::Vector4d &diffuse, bool spotlight) {
|
|
|
|
float zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
|
|
|
|
|
|
glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, diffuse.getData());
|
|
|
|
glLightfv(GL_LIGHT0 + index, GL_AMBIENT, zero);
|
|
|
|
glLightfv(GL_LIGHT0 + index, GL_SPECULAR, zero);
|
2020-08-14 16:38:17 +02:00
|
|
|
|
|
|
|
_lightPositions[index].x() = position.x();
|
|
|
|
_lightPositions[index].y() = position.y();
|
|
|
|
_lightPositions[index].z() = position.z();
|
|
|
|
_lightPositions[index].w() = 1.0f;
|
2020-07-31 21:16:38 +02:00
|
|
|
|
|
|
|
if (spotlight) {
|
2020-08-14 16:38:17 +02:00
|
|
|
_lightDirections[index] = direction;
|
2020-07-31 21:16:38 +02:00
|
|
|
glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, direction.getData());
|
|
|
|
|
2020-08-25 15:46:26 +02:00
|
|
|
glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, 0.0f);
|
2020-07-31 21:16:38 +02:00
|
|
|
// wme sets the phi angle to 1.0 (in radians)
|
|
|
|
// so either 180/pi or (180/pi)/2 should give the same result
|
2020-09-23 23:20:23 +02:00
|
|
|
glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, (180.0f / (float)M_PI));
|
2020-07-31 21:16:38 +02:00
|
|
|
} else {
|
|
|
|
glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-29 00:19:20 +02:00
|
|
|
void BaseRenderOpenGL3D::enableCulling() {
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BaseRenderOpenGL3D::disableCulling() {
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
}
|
|
|
|
|
2020-07-04 20:12:49 +02:00
|
|
|
bool BaseRenderOpenGL3D::enableShadows() {
|
|
|
|
warning("BaseRenderOpenGL3D::enableShadows not implemented yet");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BaseRenderOpenGL3D::disableShadows() {
|
2020-08-28 19:13:17 +02:00
|
|
|
warning("BaseRenderOpenGL3D::disableShadows not implemented yet");
|
2020-07-04 20:12:49 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-08-16 19:36:55 +02:00
|
|
|
void BaseRenderOpenGL3D::displayShadow(BaseObject *object, const Math::Vector3d &lightPos, bool lightPosRelative) {
|
|
|
|
BaseSurface *shadowImage = _gameRef->_shadowImage;
|
|
|
|
|
|
|
|
if (object->_shadowImage) {
|
|
|
|
shadowImage = object->_shadowImage;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!shadowImage) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Math::Matrix4 scale;
|
|
|
|
scale.setToIdentity();
|
|
|
|
scale(0, 0) = object->_shadowSize * object->_scale3D;
|
|
|
|
scale(1, 1) = 1.0f;
|
|
|
|
scale(2, 2) = object->_shadowSize * object->_scale3D;
|
|
|
|
|
|
|
|
float sinOfAngle = object->_angle.getSine();
|
|
|
|
float cosOfAngle = object->_angle.getCosine();
|
|
|
|
Math::Matrix4 rotation;
|
|
|
|
rotation.setToIdentity();
|
|
|
|
rotation(0, 0) = cosOfAngle;
|
|
|
|
rotation(0, 2) = sinOfAngle;
|
|
|
|
rotation(2, 0) = -sinOfAngle;
|
|
|
|
rotation(2, 2) = cosOfAngle;
|
|
|
|
Math::Matrix4 translation;
|
|
|
|
translation.setToIdentity();
|
|
|
|
translation.setPosition(object->_posVector);
|
|
|
|
|
|
|
|
Math::Matrix4 worldTransformation = translation * rotation * scale;
|
|
|
|
worldTransformation.transpose();
|
|
|
|
worldTransformation = worldTransformation * _lastViewMatrix;
|
|
|
|
|
|
|
|
glLoadMatrixf(worldTransformation.getData());
|
|
|
|
|
2021-12-30 13:08:14 +01:00
|
|
|
glDepthMask(GL_FALSE);
|
2020-08-16 19:36:55 +02:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
static_cast<BaseSurfaceOpenGL3D *>(shadowImage)->setTexture();
|
|
|
|
|
2020-10-22 16:43:15 +02:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, sizeof(SimpleShadowVertex), &_simpleShadow[0].x);
|
|
|
|
glNormalPointer(GL_FLOAT, sizeof(SimpleShadowVertex), &_simpleShadow[0].nx);
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, sizeof(SimpleShadowVertex), &_simpleShadow[0].u);
|
|
|
|
|
2020-08-16 19:36:55 +02:00
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
|
|
|
2021-12-30 13:08:14 +01:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
|
|
|
|
glDepthMask(GL_TRUE);
|
2020-08-16 19:36:55 +02:00
|
|
|
glLoadMatrixf(_lastViewMatrix.getData());
|
|
|
|
}
|
|
|
|
|
2020-07-04 20:12:49 +02:00
|
|
|
bool BaseRenderOpenGL3D::stencilSupported() {
|
|
|
|
// assume that we have a stencil buffer
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
BaseImage *BaseRenderOpenGL3D::takeScreenshot() {
|
2020-06-01 12:51:58 +02:00
|
|
|
warning("BaseRenderOpenGL3D::takeScreenshot not yet implemented");
|
2020-05-19 16:23:53 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::saveScreenShot(const Common::String &filename, int sizeX, int sizeY) {
|
2020-06-01 12:51:58 +02:00
|
|
|
warning("BaseRenderOpenGL3D::saveScreenshot not yet implemented");
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
void BaseRenderOpenGL3D::setWindowed(bool windowed) {
|
2022-07-13 22:26:29 +02:00
|
|
|
ConfMan.setBool("fullscreen", !windowed);
|
|
|
|
g_system->beginGFXTransaction();
|
|
|
|
g_system->setFeatureState(OSystem::kFeatureFullscreenMode, !windowed);
|
|
|
|
g_system->endGFXTransaction();
|
2020-05-19 16:23:53 +02:00
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
void BaseRenderOpenGL3D::fadeToColor(byte r, byte g, byte b, byte a) {
|
2020-05-21 19:45:32 +02:00
|
|
|
setProjection2D();
|
|
|
|
|
2020-06-01 15:47:29 +02:00
|
|
|
const int vertexSize = 16;
|
|
|
|
byte vertices[4 * vertexSize];
|
|
|
|
float *vertexCoords = reinterpret_cast<float *>(vertices);
|
|
|
|
|
|
|
|
vertexCoords[0 * 4 + 1] = _viewportRect.left;
|
|
|
|
vertexCoords[0 * 4 + 2] = _viewportRect.bottom;
|
|
|
|
vertexCoords[0 * 4 + 3] = 0.0f;
|
|
|
|
vertexCoords[1 * 4 + 1] = _viewportRect.left;
|
|
|
|
vertexCoords[1 * 4 + 2] = _viewportRect.top;
|
|
|
|
vertexCoords[1 * 4 + 3] = 0.0f;
|
|
|
|
vertexCoords[2 * 4 + 1] = _viewportRect.right;
|
|
|
|
vertexCoords[2 * 4 + 2] = _viewportRect.bottom;
|
|
|
|
vertexCoords[2 * 4 + 3] = 0.0f;
|
|
|
|
vertexCoords[3 * 4 + 1] = _viewportRect.right;
|
|
|
|
vertexCoords[3 * 4 + 2] = _viewportRect.top;
|
|
|
|
vertexCoords[3 * 4 + 3] = 0.0f;
|
|
|
|
|
|
|
|
vertices[0 * vertexSize + 0] = r;
|
|
|
|
vertices[0 * vertexSize + 1] = g;
|
|
|
|
vertices[0 * vertexSize + 2] = b;
|
|
|
|
vertices[0 * vertexSize + 3] = a;
|
|
|
|
vertices[1 * vertexSize + 0] = r;
|
|
|
|
vertices[1 * vertexSize + 1] = g;
|
|
|
|
vertices[1 * vertexSize + 2] = b;
|
|
|
|
vertices[1 * vertexSize + 3] = a;
|
|
|
|
vertices[2 * vertexSize + 0] = r;
|
|
|
|
vertices[2 * vertexSize + 1] = g;
|
|
|
|
vertices[2 * vertexSize + 2] = b;
|
|
|
|
vertices[2 * vertexSize + 3] = a;
|
|
|
|
vertices[3 * vertexSize + 0] = r;
|
|
|
|
vertices[3 * vertexSize + 1] = g;
|
|
|
|
vertices[3 * vertexSize + 2] = b;
|
|
|
|
vertices[3 * vertexSize + 3] = a;
|
2020-05-21 19:45:32 +02:00
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
2021-12-30 13:08:14 +01:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
2020-05-21 19:45:32 +02:00
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
2020-06-01 15:47:29 +02:00
|
|
|
glVertexPointer(3, GL_FLOAT, vertexSize, vertices + 4);
|
|
|
|
glColorPointer(4, GL_UNSIGNED_BYTE, vertexSize, vertices);
|
2020-05-21 19:45:32 +02:00
|
|
|
|
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
|
|
|
2021-12-30 13:08:14 +01:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
2020-05-19 16:23:53 +02:00
|
|
|
setup2D(true);
|
|
|
|
}
|
|
|
|
|
2020-08-01 15:48:04 +02:00
|
|
|
bool BaseRenderOpenGL3D::fill(byte r, byte g, byte b, Common::Rect *rect) {
|
2021-12-30 13:04:58 +01:00
|
|
|
glClearColor(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f);
|
2020-08-01 15:48:04 +02:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BaseRenderOpenGL3D::setViewport(int left, int top, int right, int bottom) {
|
|
|
|
_viewportRect.setRect(left, top, right, bottom);
|
2020-08-10 19:27:41 +02:00
|
|
|
glViewport(left, _height - bottom, right - left, bottom - top);
|
2020-08-01 15:48:04 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::drawLine(int x1, int y1, int x2, int y2, uint32 color) {
|
2020-08-28 01:40:30 +02:00
|
|
|
byte a = RGBCOLGetA(color);
|
|
|
|
byte r = RGBCOLGetR(color);
|
|
|
|
byte g = RGBCOLGetG(color);
|
|
|
|
byte b = RGBCOLGetB(color);
|
|
|
|
|
|
|
|
glBegin(GL_LINES);
|
2021-12-30 13:08:14 +01:00
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
glVertex3f(x1, y1, 0.9f);
|
|
|
|
glVertex3f(x2, y2, 0.9f);
|
2020-08-28 01:40:30 +02:00
|
|
|
glEnd();
|
|
|
|
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::drawRect(int x1, int y1, int x2, int y2, uint32 color, int width) {
|
2020-06-01 12:51:58 +02:00
|
|
|
warning("BaseRenderOpenGL3D::drawRect not yet implemented");
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-09 01:11:50 +02:00
|
|
|
bool BaseRenderOpenGL3D::setProjection() {
|
2020-05-19 21:29:00 +02:00
|
|
|
// is the viewport already set here?
|
|
|
|
float viewportWidth = _viewportRect.right - _viewportRect.left;
|
|
|
|
float viewportHeight = _viewportRect.bottom - _viewportRect.top;
|
|
|
|
|
2020-06-09 01:11:50 +02:00
|
|
|
float verticalViewAngle = _fov;
|
2021-12-30 13:04:58 +01:00
|
|
|
float aspectRatio = viewportWidth / viewportHeight;
|
2020-08-22 03:43:14 +02:00
|
|
|
float top = _nearPlane * tanf(verticalViewAngle * 0.5f);
|
2020-05-19 21:29:00 +02:00
|
|
|
|
2021-12-30 13:04:58 +01:00
|
|
|
float scaleMod = _height / viewportHeight;
|
2020-08-10 19:24:38 +02:00
|
|
|
|
2020-05-19 21:29:00 +02:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2020-08-22 03:43:14 +02:00
|
|
|
glFrustum(-top * aspectRatio, top * aspectRatio, -top, top, _nearPlane, _farPlane);
|
2020-07-31 16:44:40 +02:00
|
|
|
glGetFloatv(GL_PROJECTION_MATRIX, _projectionMatrix3d.getData());
|
2020-08-10 19:24:38 +02:00
|
|
|
|
|
|
|
_projectionMatrix3d(0, 0) *= scaleMod;
|
|
|
|
_projectionMatrix3d(1, 1) *= scaleMod;
|
|
|
|
|
|
|
|
glLoadMatrixf(_projectionMatrix3d.getData());
|
|
|
|
|
2020-05-19 21:29:00 +02:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::setProjection2D() {
|
2020-05-21 19:45:03 +02:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2020-08-10 19:30:57 +02:00
|
|
|
glOrtho(0, _width, 0, _height, -1.0, 100.0);
|
2020-05-21 19:45:03 +02:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-07-31 16:44:40 +02:00
|
|
|
void BaseRenderOpenGL3D::setWorldTransform(const Math::Matrix4 &transform) {
|
|
|
|
Math::Matrix4 tmp = transform;
|
|
|
|
tmp.transpose();
|
|
|
|
Math::Matrix4 newModelViewTransform = tmp * _lastViewMatrix;
|
|
|
|
glLoadMatrixf(newModelViewTransform.getData());
|
2020-06-02 18:33:21 +02:00
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::windowedBlt() {
|
2020-06-01 12:51:58 +02:00
|
|
|
warning("BaseRenderOpenGL3D::windowedBlt not yet implemented");
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Wintermute::BaseRenderOpenGL3D::onWindowChange() {
|
2022-07-13 22:26:29 +02:00
|
|
|
_windowed = !g_system->getFeatureState(OSystem::kFeatureFullscreenMode);
|
2020-05-19 16:23:53 +02:00
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::initRenderer(int width, int height, bool windowed) {
|
2022-07-13 22:26:29 +02:00
|
|
|
_windowed = !ConfMan.getBool("fullscreen");
|
2020-05-19 16:23:53 +02:00
|
|
|
_width = width;
|
|
|
|
_height = height;
|
2020-05-19 21:29:00 +02:00
|
|
|
|
2020-08-24 18:19:14 +02:00
|
|
|
_nearPlane = 90.0f;
|
|
|
|
_farPlane = 10000.0f;
|
|
|
|
|
2020-05-21 03:40:57 +02:00
|
|
|
setViewport(0, 0, width, height);
|
2020-05-19 21:29:00 +02:00
|
|
|
|
|
|
|
_active = true;
|
2020-05-19 21:51:52 +02:00
|
|
|
// setup a proper state
|
|
|
|
setup2D(true);
|
2020-08-16 19:36:55 +02:00
|
|
|
|
|
|
|
_simpleShadow[0].x = -1.0f;
|
|
|
|
_simpleShadow[0].y = 0.0f;
|
|
|
|
_simpleShadow[0].z = -1.0f;
|
|
|
|
_simpleShadow[0].nx = 0.0f;
|
|
|
|
_simpleShadow[0].ny = 1.0f;
|
|
|
|
_simpleShadow[0].nz = 0.0f;
|
|
|
|
_simpleShadow[0].u = 0.0f;
|
|
|
|
_simpleShadow[0].v = 1.0f;
|
|
|
|
|
|
|
|
_simpleShadow[1].x = -1.0f;
|
|
|
|
_simpleShadow[1].y = 0.0f;
|
|
|
|
_simpleShadow[1].z = 1.0f;
|
|
|
|
_simpleShadow[1].nx = 0.0f;
|
|
|
|
_simpleShadow[1].ny = 1.0f;
|
|
|
|
_simpleShadow[1].nz = 0.0f;
|
|
|
|
_simpleShadow[1].u = 1.0f;
|
|
|
|
_simpleShadow[1].v = 1.0f;
|
|
|
|
|
|
|
|
_simpleShadow[2].x = 1.0f;
|
|
|
|
_simpleShadow[2].y = 0.0f;
|
|
|
|
_simpleShadow[2].z = -1.0f;
|
|
|
|
_simpleShadow[2].nx = 0.0f;
|
|
|
|
_simpleShadow[2].ny = 1.0f;
|
|
|
|
_simpleShadow[2].nz = 0.0f;
|
|
|
|
_simpleShadow[2].u = 0.0f;
|
|
|
|
_simpleShadow[2].v = 0.0f;
|
|
|
|
|
|
|
|
_simpleShadow[3].x = 1.0f;
|
|
|
|
_simpleShadow[3].y = 0.0f;
|
|
|
|
_simpleShadow[3].z = 1.0f;
|
|
|
|
_simpleShadow[3].nx = 0.0f;
|
|
|
|
_simpleShadow[3].ny = 1.0f;
|
|
|
|
_simpleShadow[3].nz = 0.0f;
|
|
|
|
_simpleShadow[3].u = 1.0f;
|
|
|
|
_simpleShadow[3].v = 0.0f;
|
|
|
|
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Wintermute::BaseRenderOpenGL3D::flip() {
|
|
|
|
g_system->updateScreen();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::indicatorFlip() {
|
2020-06-01 12:51:58 +02:00
|
|
|
warning("BaseRenderOpenGL3D::indicatorFlip not yet implemented");
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::forcedFlip() {
|
2022-07-13 22:26:29 +02:00
|
|
|
g_system->updateScreen();
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::setup2D(bool force) {
|
2020-08-27 14:06:25 +02:00
|
|
|
if (_renderState != RSTATE_2D || force) {
|
|
|
|
_renderState = RSTATE_2D;
|
2020-05-19 21:29:52 +02:00
|
|
|
|
|
|
|
// some states are still missing here
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
2020-05-31 15:30:23 +02:00
|
|
|
glDisable(GL_STENCIL_TEST);
|
2020-05-19 21:29:52 +02:00
|
|
|
glDisable(GL_FOG);
|
|
|
|
|
|
|
|
glEnable(GL_CULL_FACE);
|
2020-05-31 15:30:23 +02:00
|
|
|
glFrontFace(GL_CCW);
|
2020-05-19 21:29:52 +02:00
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
glEnable(GL_BLEND);
|
2020-05-29 13:11:53 +02:00
|
|
|
glAlphaFunc(GL_GEQUAL, 0.0f);
|
2020-05-19 21:29:52 +02:00
|
|
|
glPolygonMode(GL_FRONT, GL_FILL);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
2020-08-10 19:30:57 +02:00
|
|
|
glViewport(0, 0, _width, _height);
|
2020-05-21 19:45:03 +02:00
|
|
|
setProjection2D();
|
2020-05-19 21:29:52 +02:00
|
|
|
}
|
|
|
|
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-07-09 21:33:38 +02:00
|
|
|
bool BaseRenderOpenGL3D::setup3D(Camera3D *camera, bool force) {
|
2020-08-27 14:06:25 +02:00
|
|
|
if (_renderState != RSTATE_3D || force) {
|
|
|
|
_renderState = RSTATE_3D;
|
2020-05-26 13:10:42 +02:00
|
|
|
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
2020-07-06 19:59:40 +02:00
|
|
|
glEnable(GL_LIGHTING);
|
2020-05-26 13:10:42 +02:00
|
|
|
glEnable(GL_BLEND);
|
2020-08-16 19:35:32 +02:00
|
|
|
// wme uses 8 as a reference value and Direct3D expects it to be in the range [0, 255]
|
|
|
|
// 8 / 255 ~ 0.0313
|
|
|
|
glAlphaFunc(GL_GEQUAL, 0.0313);
|
2020-05-26 13:10:42 +02:00
|
|
|
|
2020-07-06 23:52:19 +02:00
|
|
|
setAmbientLight();
|
|
|
|
|
2020-07-07 00:25:03 +02:00
|
|
|
glEnable(GL_NORMALIZE);
|
|
|
|
|
2020-07-09 21:33:38 +02:00
|
|
|
if (camera) {
|
|
|
|
_fov = camera->_fov;
|
|
|
|
|
2020-08-22 03:43:14 +02:00
|
|
|
if (camera->_nearClipPlane >= 0.0f) {
|
|
|
|
_nearPlane = camera->_nearClipPlane;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (camera->_farClipPlane >= 0.0f) {
|
|
|
|
_farPlane = camera->_farClipPlane;
|
|
|
|
}
|
|
|
|
|
2020-07-09 21:33:38 +02:00
|
|
|
Math::Matrix4 viewMatrix;
|
|
|
|
camera->getViewMatrix(&viewMatrix);
|
2020-08-25 15:32:57 +02:00
|
|
|
glLoadMatrixf(viewMatrix.getData());
|
2020-07-09 21:33:38 +02:00
|
|
|
glTranslatef(-camera->_position.x(), -camera->_position.y(), -camera->_position.z());
|
|
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, _lastViewMatrix.getData());
|
2020-08-25 15:32:57 +02:00
|
|
|
} else {
|
|
|
|
glLoadMatrixf(_lastViewMatrix.getData());
|
2020-07-09 21:33:38 +02:00
|
|
|
}
|
2020-05-28 01:38:14 +02:00
|
|
|
|
2020-08-14 16:38:17 +02:00
|
|
|
for (int i = 0; i < maximumLightsCount(); ++i) {
|
|
|
|
glLightfv(GL_LIGHT0 + i, GL_POSITION, _lightPositions[i].getData());
|
|
|
|
glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, _lightDirections[i].getData());
|
|
|
|
}
|
|
|
|
|
2022-07-02 22:39:01 +02:00
|
|
|
bool fogEnabled;
|
|
|
|
uint32 fogColor;
|
|
|
|
float fogStart, fogEnd;
|
2020-07-15 16:28:44 +02:00
|
|
|
|
2022-07-02 22:39:01 +02:00
|
|
|
_gameRef->getFogParams(&fogEnabled, &fogColor, &fogStart, &fogEnd);
|
|
|
|
if (fogEnabled) {
|
2020-07-15 16:28:44 +02:00
|
|
|
glEnable(GL_FOG);
|
|
|
|
glFogi(GL_FOG_MODE, GL_LINEAR);
|
2022-07-02 22:39:01 +02:00
|
|
|
glFogf(GL_FOG_START, fogStart);
|
|
|
|
glFogf(GL_FOG_END, fogEnd);
|
2020-07-15 16:28:44 +02:00
|
|
|
|
2021-12-30 13:49:35 +01:00
|
|
|
GLfloat color[4] = { RGBCOLGetR(fogColor) / 255.0f,
|
|
|
|
RGBCOLGetG(fogColor) / 255.0f,
|
|
|
|
RGBCOLGetB(fogColor) / 255.0f,
|
|
|
|
RGBCOLGetA(fogColor) / 255.0f };
|
2020-07-15 16:28:44 +02:00
|
|
|
glFogfv(GL_FOG_COLOR, color);
|
|
|
|
} else {
|
|
|
|
glDisable(GL_FOG);
|
|
|
|
}
|
|
|
|
|
2020-08-10 19:46:00 +02:00
|
|
|
glViewport(_viewportRect.left, _height - _viewportRect.bottom, _viewportRect.width(), _viewportRect.height());
|
|
|
|
_viewport3dRect = _viewportRect;
|
2020-07-09 21:33:38 +02:00
|
|
|
setProjection();
|
2020-05-26 13:10:42 +02:00
|
|
|
}
|
|
|
|
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
bool BaseRenderOpenGL3D::setupLines() {
|
2020-08-28 01:40:30 +02:00
|
|
|
if (_renderState != RSTATE_LINES) {
|
|
|
|
_renderState = RSTATE_LINES;
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
2021-12-30 13:08:14 +01:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
2020-08-28 01:40:30 +02:00
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
}
|
|
|
|
|
2020-05-19 18:32:27 +02:00
|
|
|
return true;
|
2020-05-19 16:23:53 +02:00
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
BaseSurface *Wintermute::BaseRenderOpenGL3D::createSurface() {
|
2020-06-25 20:10:22 +02:00
|
|
|
return new BaseSurfaceOpenGL3D(_gameRef, this);
|
2020-05-19 16:23:53 +02:00
|
|
|
}
|
|
|
|
|
2020-06-21 20:53:04 +02:00
|
|
|
struct SpriteVertex {
|
|
|
|
float u;
|
|
|
|
float v;
|
2021-12-29 23:23:55 +01:00
|
|
|
float x;
|
|
|
|
float y;
|
|
|
|
float z;
|
2020-06-21 20:53:04 +02:00
|
|
|
uint8 r;
|
|
|
|
uint8 g;
|
|
|
|
uint8 b;
|
|
|
|
uint8 a;
|
2021-12-29 23:23:55 +01:00
|
|
|
};
|
2020-06-21 20:53:04 +02:00
|
|
|
|
2020-06-16 00:17:43 +02:00
|
|
|
bool BaseRenderOpenGL3D::drawSpriteEx(BaseSurfaceOpenGL3D &tex, const Wintermute::Rect32 &rect,
|
2021-12-30 13:49:35 +01:00
|
|
|
const Wintermute::Vector2 &pos, const Wintermute::Vector2 &rot, const Wintermute::Vector2 &scale,
|
|
|
|
float angle, uint32 color, bool alphaDisable, Graphics::TSpriteBlendMode blendMode,
|
|
|
|
bool mirrorX, bool mirrorY) {
|
2020-05-19 18:33:49 +02:00
|
|
|
// original wme has a batch mode for sprites, we ignore this for the moment
|
|
|
|
|
2020-06-19 19:04:55 +02:00
|
|
|
if (_forceAlphaColor != 0) {
|
|
|
|
color = _forceAlphaColor;
|
|
|
|
}
|
|
|
|
|
2020-05-19 18:33:49 +02:00
|
|
|
float width = (rect.right - rect.left) * scale.x;
|
|
|
|
float height = (rect.bottom - rect.top) * scale.y;
|
|
|
|
|
2020-06-16 00:17:43 +02:00
|
|
|
glBindTexture(GL_TEXTURE_2D, tex.getTextureName());
|
|
|
|
|
2020-06-21 20:53:04 +02:00
|
|
|
// for sprites we clamp to the edge, to avoid line fragments at the edges
|
|
|
|
// this is not done by wme, though
|
2020-06-16 00:17:43 +02:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
|
2020-10-17 23:25:48 +02:00
|
|
|
int texWidth = tex.getGLTextureWidth();
|
|
|
|
int texHeight = tex.getGLTextureHeight();
|
2020-06-16 00:17:43 +02:00
|
|
|
|
|
|
|
float texLeft = (float)rect.left / (float)texWidth;
|
|
|
|
float texTop = (float)rect.top / (float)texHeight;
|
|
|
|
float texRight = (float)rect.right / (float)texWidth;
|
|
|
|
float texBottom = (float)rect.bottom / (float)texHeight;
|
2020-05-19 18:33:49 +02:00
|
|
|
|
2020-08-10 19:30:57 +02:00
|
|
|
float offset = _height / 2.0f;
|
2020-06-21 20:53:04 +02:00
|
|
|
float correctedYPos = (pos.y - offset) * -1.0f + offset;
|
2020-05-22 00:00:35 +02:00
|
|
|
|
2020-05-28 13:39:23 +02:00
|
|
|
if (mirrorX) {
|
2020-08-17 15:00:59 +02:00
|
|
|
SWAP(texLeft, texRight);
|
2020-05-19 18:33:49 +02:00
|
|
|
}
|
|
|
|
|
2020-05-28 13:39:23 +02:00
|
|
|
if (mirrorY) {
|
2020-08-17 15:00:59 +02:00
|
|
|
SWAP(texTop, texBottom);
|
2020-05-19 18:33:49 +02:00
|
|
|
}
|
|
|
|
|
2020-06-21 20:53:04 +02:00
|
|
|
SpriteVertex vertices[4] = {};
|
2020-05-19 18:33:49 +02:00
|
|
|
|
|
|
|
// texture coords
|
2020-06-21 20:53:04 +02:00
|
|
|
vertices[0].u = texLeft;
|
|
|
|
vertices[0].v = texTop;
|
|
|
|
|
|
|
|
vertices[1].u = texLeft;
|
|
|
|
vertices[1].v = texBottom;
|
|
|
|
|
|
|
|
vertices[2].u = texRight;
|
|
|
|
vertices[2].v = texTop;
|
|
|
|
|
|
|
|
vertices[3].u = texRight;
|
|
|
|
vertices[3].v = texBottom;
|
2020-05-19 18:33:49 +02:00
|
|
|
|
|
|
|
// position coords
|
2021-06-12 22:56:31 +03:00
|
|
|
vertices[0].x = pos.x;
|
|
|
|
vertices[0].y = correctedYPos;
|
2020-06-21 20:53:04 +02:00
|
|
|
vertices[0].z = -0.9f;
|
|
|
|
|
2021-06-12 22:56:31 +03:00
|
|
|
vertices[1].x = pos.x;
|
|
|
|
vertices[1].y = correctedYPos - height;
|
2020-06-21 20:53:04 +02:00
|
|
|
vertices[1].z = -0.9f;
|
|
|
|
|
2021-06-12 22:56:31 +03:00
|
|
|
vertices[2].x = pos.x + width;
|
|
|
|
vertices[2].y = correctedYPos;
|
2020-06-21 20:53:04 +02:00
|
|
|
vertices[2].z = -0.9f;
|
|
|
|
|
2021-06-12 22:56:31 +03:00
|
|
|
vertices[3].x = pos.x + width;
|
|
|
|
vertices[3].y = correctedYPos - height;
|
2020-06-21 20:53:04 +02:00
|
|
|
vertices[3].z = -0.9f;
|
2020-05-21 03:45:20 +02:00
|
|
|
|
|
|
|
// not exactly sure about the color format, but this seems to work
|
|
|
|
byte a = RGBCOLGetA(color);
|
|
|
|
byte r = RGBCOLGetR(color);
|
|
|
|
byte g = RGBCOLGetG(color);
|
|
|
|
byte b = RGBCOLGetB(color);
|
|
|
|
|
2020-06-21 20:53:04 +02:00
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
vertices[i].r = r;
|
|
|
|
vertices[i].g = g;
|
|
|
|
vertices[i].b = b;
|
|
|
|
vertices[i].a = a;
|
|
|
|
}
|
2020-05-19 18:33:49 +02:00
|
|
|
|
2020-08-18 18:52:57 +02:00
|
|
|
if (angle != 0) {
|
|
|
|
Vector2 correctedRot(rot.x, (rot.y - offset) * -1.0f + offset);
|
|
|
|
Math::Matrix3 transform = build2dTransformation(correctedRot, angle);
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
Math::Vector3d vertexPostion(vertices[i].x, vertices[i].y, 1.0f);
|
|
|
|
transform.transformVector(&vertexPostion);
|
|
|
|
|
|
|
|
vertices[i].x = vertexPostion.x();
|
|
|
|
vertices[i].y = vertexPostion.y();
|
|
|
|
}
|
|
|
|
}
|
2020-05-19 18:33:49 +02:00
|
|
|
|
2020-05-28 13:39:23 +02:00
|
|
|
if (alphaDisable) {
|
2020-05-21 03:45:20 +02:00
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
}
|
|
|
|
|
2020-06-24 21:39:43 +02:00
|
|
|
setSpriteBlendMode(blendMode);
|
|
|
|
|
2020-05-21 03:45:20 +02:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
2020-10-22 16:43:15 +02:00
|
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, sizeof(SpriteVertex), &vertices[0].x);
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, sizeof(SpriteVertex), &vertices[0].u);
|
|
|
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(SpriteVertex), &vertices[0].r);
|
2020-05-21 03:45:20 +02:00
|
|
|
|
2020-05-19 18:33:49 +02:00
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
|
|
|
2021-12-30 13:08:14 +01:00
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
|
2020-05-28 13:39:23 +02:00
|
|
|
if (alphaDisable) {
|
2020-05-21 03:45:20 +02:00
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
}
|
|
|
|
|
2020-05-19 16:23:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
2020-06-01 12:42:14 +02:00
|
|
|
|
2020-08-07 14:10:22 +02:00
|
|
|
void BaseRenderOpenGL3D::renderSceneGeometry(const BaseArray<AdWalkplane *> &planes, const BaseArray<AdBlock *> &blocks,
|
2021-12-30 13:49:35 +01:00
|
|
|
const BaseArray<AdGeneric *> &generics, const BaseArray<Light3D *> &lights, Camera3D *camera) {
|
2020-10-17 23:59:10 +02:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
2020-08-02 00:44:16 +02:00
|
|
|
_gameRef->_renderer3D->setup3D(camera, true);
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glFrontFace(GL_CCW);
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
2020-08-03 18:34:55 +02:00
|
|
|
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
|
|
|
|
glEnable(GL_COLOR_MATERIAL);
|
2020-08-02 00:44:16 +02:00
|
|
|
|
2021-12-30 13:08:14 +01:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
2020-08-02 00:44:16 +02:00
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
|
|
|
// render walk planes
|
|
|
|
for (uint i = 0; i < planes.size(); i++) {
|
2020-08-28 15:41:42 +02:00
|
|
|
if (planes[i]->_active) {
|
|
|
|
planes[i]->_mesh->render();
|
2020-08-02 00:44:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// render blocks
|
|
|
|
for (uint i = 0; i < blocks.size(); i++) {
|
2020-08-28 15:41:42 +02:00
|
|
|
if (blocks[i]->_active) {
|
|
|
|
blocks[i]->_mesh->render();
|
2020-08-02 00:44:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// render generic objects
|
|
|
|
for (uint i = 0; i < generics.size(); i++) {
|
2020-08-28 15:41:42 +02:00
|
|
|
if (generics[i]->_active) {
|
|
|
|
generics[i]->_mesh->render();
|
2020-08-02 00:44:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-07 14:10:22 +02:00
|
|
|
for (uint i = 0; i < lights.size(); ++i) {
|
2020-08-28 15:41:42 +02:00
|
|
|
if (lights[i]->_active) {
|
|
|
|
glBegin(GL_LINES);
|
|
|
|
glColor3f(1.0f, 1.0f, 0.0f);
|
|
|
|
Math::Vector3d right = lights[i]->_position + Math::Vector3d(1000.0f, 0.0f, 0.0f);
|
|
|
|
Math::Vector3d up = lights[i]->_position + Math::Vector3d(0.0f, 1000.0f, 0.0f);
|
|
|
|
Math::Vector3d backward = lights[i]->_position + Math::Vector3d(0.0f, 0.0f, 1000.0f);
|
|
|
|
Math::Vector3d left = lights[i]->_position + Math::Vector3d(-1000.0f, 0.0f, 0.0f);
|
|
|
|
Math::Vector3d down = lights[i]->_position + Math::Vector3d(0.0f, -1000.0f, 0.0f);
|
|
|
|
Math::Vector3d forward = lights[i]->_position + Math::Vector3d(0.0f, 0.0f, -1000.0f);
|
|
|
|
|
|
|
|
glVertex3fv(lights[i]->_position.getData());
|
|
|
|
glVertex3fv(right.getData());
|
|
|
|
glVertex3fv(lights[i]->_position.getData());
|
|
|
|
glVertex3fv(up.getData());
|
|
|
|
glVertex3fv(lights[i]->_position.getData());
|
|
|
|
glVertex3fv(backward.getData());
|
|
|
|
glVertex3fv(lights[i]->_position.getData());
|
|
|
|
glVertex3fv(left.getData());
|
|
|
|
glVertex3fv(lights[i]->_position.getData());
|
|
|
|
glVertex3fv(down.getData());
|
|
|
|
glVertex3fv(lights[i]->_position.getData());
|
|
|
|
glVertex3fv(forward.getData());
|
|
|
|
glEnd();
|
2020-08-07 14:10:22 +02:00
|
|
|
}
|
|
|
|
}
|
2020-08-02 00:44:16 +02:00
|
|
|
|
2020-08-03 18:34:55 +02:00
|
|
|
glDisable(GL_COLOR_MATERIAL);
|
2020-08-02 00:44:16 +02:00
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
}
|
|
|
|
|
2021-12-30 13:49:35 +01:00
|
|
|
void BaseRenderOpenGL3D::renderShadowGeometry(const BaseArray<AdWalkplane *> &planes,
|
|
|
|
const BaseArray<AdBlock *> &blocks,
|
|
|
|
const BaseArray<AdGeneric *> &generics, Camera3D *camera) {
|
2020-10-17 23:59:10 +02:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
2020-08-02 00:44:16 +02:00
|
|
|
setup3D(camera, true);
|
|
|
|
|
|
|
|
// disable color write
|
|
|
|
glBlendFunc(GL_ZERO, GL_ONE);
|
|
|
|
|
|
|
|
glFrontFace(GL_CCW);
|
2021-12-30 13:08:14 +01:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
2020-08-02 00:44:16 +02:00
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
|
|
|
// render walk planes
|
|
|
|
for (uint i = 0; i < planes.size(); i++) {
|
|
|
|
if (planes[i]->_active && planes[i]->_receiveShadows) {
|
|
|
|
planes[i]->_mesh->render();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// render blocks
|
|
|
|
for (uint i = 0; i < blocks.size(); i++) {
|
|
|
|
if (blocks[i]->_active && blocks[i]->_receiveShadows) {
|
|
|
|
blocks[i]->_mesh->render();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// render generic objects
|
|
|
|
for (uint i = 0; i < generics.size(); i++) {
|
|
|
|
if (generics[i]->_active && generics[i]->_receiveShadows) {
|
|
|
|
generics[i]->_mesh->render();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setSpriteBlendMode(Graphics::BLEND_NORMAL);
|
|
|
|
}
|
|
|
|
|
2020-07-21 04:14:33 +02:00
|
|
|
Mesh3DS *BaseRenderOpenGL3D::createMesh3DS() {
|
|
|
|
return new Mesh3DSOpenGL();
|
|
|
|
}
|
|
|
|
|
|
|
|
MeshX *BaseRenderOpenGL3D::createMeshX() {
|
|
|
|
return new MeshXOpenGL(_gameRef);
|
|
|
|
}
|
|
|
|
|
2020-07-29 22:54:08 +02:00
|
|
|
ShadowVolume *BaseRenderOpenGL3D::createShadowVolume() {
|
|
|
|
return new ShadowVolumeOpenGL(_gameRef);
|
|
|
|
}
|
|
|
|
|
2020-06-01 12:42:14 +02:00
|
|
|
} // namespace Wintermute
|
2020-10-06 07:33:01 +02:00
|
|
|
|
2021-11-17 23:56:21 +00:00
|
|
|
#endif // defined(USE_OPENGL_GAME)
|