WINTERMUTE: Implement image based shadows in fixed function renderer

This commit is contained in:
Gunnar Birke 2020-08-16 19:36:55 +02:00 committed by Paweł Kołodziejski
parent c570f4f609
commit a34a125848
6 changed files with 108 additions and 2 deletions

View file

@ -382,8 +382,7 @@ bool AdActor3DX::display() {
if (ShadowType == SHADOW_STENCIL) {
displayShadowVolume();
} else if (ShadowType > SHADOW_NONE) {
warning("AdActor3DX::display simple or flat shadows are not implemented yet");
//m_Renderer->DisplayShadow(this, Math::Vector3d(_shadowLightPos.x() * _scale3D, _shadowLightPos.y() * _scale3D, _shadowLightPos.z() * _scale3D), NULL, true);
_gameRef->_renderer3D->displayShadow(this, Math::Vector3d(_shadowLightPos.x() * _scale3D, _shadowLightPos.y() * _scale3D, _shadowLightPos.z() * _scale3D), true);
}
_gameRef->_renderer3D->setSpriteBlendMode(_blendMode);

View file

@ -143,6 +143,53 @@ bool BaseRenderOpenGL3D::disableShadows() {
return true;
}
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());
glDepthMask(false);
glEnable(GL_TEXTURE_2D);
static_cast<BaseSurfaceOpenGL3D *>(shadowImage)->setTexture();
glInterleavedArrays(GL_T2F_N3F_V3F, 0, _simpleShadow);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDepthMask(true);
glLoadMatrixf(_lastViewMatrix.getData());
}
bool BaseRenderOpenGL3D::stencilSupported() {
// assume that we have a stencil buffer
return true;
@ -307,6 +354,43 @@ bool BaseRenderOpenGL3D::initRenderer(int width, int height, bool windowed) {
_active = true;
// setup a proper state
setup2D(true);
_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;
return true;
}

View file

@ -37,6 +37,21 @@ namespace Wintermute {
class BaseSurfaceOpenGL3D;
#include "common/pack-start.h"
struct SimpleShadowVertex {
float u;
float v;
float nx;
float ny;
float nz;
float x;
float y;
float z;
} PACKED_STRUCT;
#include "common/pack-end.h"
class BaseRenderOpenGL3D : public BaseRenderer3D {
public:
BaseRenderOpenGL3D(BaseGame *inGame = nullptr);
@ -53,6 +68,7 @@ public:
bool enableShadows() override;
bool disableShadows() override;
void displayShadow(BaseObject *object, const Math::Vector3d &lightPos, bool lightPosRelative) override;
bool stencilSupported() override;
void dumpData(const char *filename) override {}
@ -121,6 +137,7 @@ public:
ShadowVolume *createShadowVolume() override;
private:
SimpleShadowVertex _simpleShadow[4];
Common::Array<Math::Vector4d> _lightPositions;
Common::Array<Math::Vector3d> _lightDirections;
float _fov;

View file

@ -161,6 +161,10 @@ bool BaseRenderOpenGL3DShader::disableShadows() {
return true;
}
void BaseRenderOpenGL3DShader::displayShadow(BaseObject *object, const Math::Vector3d &lightPos, bool lightPosRelative) {
warning("BaseRenderOpenGL3DShader::displayShadow not implemented yet");
}
bool BaseRenderOpenGL3DShader::stencilSupported() {
// assume that we have a stencil buffer
return true;

View file

@ -54,6 +54,7 @@ public:
bool enableShadows() override;
bool disableShadows() override;
void displayShadow(BaseObject *object, const Math::Vector3d &lightPos, bool lightPosRelative) override;
bool stencilSupported() override;
void dumpData(const char *filename) override {}

View file

@ -66,6 +66,7 @@ public:
virtual bool enableShadows() = 0;
virtual bool disableShadows() = 0;
virtual void displayShadow(BaseObject *object, const Math::Vector3d &light, bool lightPosRelative) = 0;
virtual bool stencilSupported() = 0;
Rect32 getViewPort() override;