mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-13 23:51:15 +00:00
This removes 3 uniforms, consisting of 9 floats. Those were merged into other values that never get used at the same time. It also moves the costly setup of the fixed colormap out of the render state into the 2D processing code. Since 3D forces use of render buffers now, it is no longer necessary to draw the entire scene with the colormap active, meaning it can be handled more efficiently.
321 lines
10 KiB
C++
321 lines
10 KiB
C++
//
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Copyright(C) 2003-2016 Christoph Oelckers
|
|
// All rights reserved.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with this program. If not, see http://www.gnu.org/licenses/
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
|
|
#include "gl_load/gl_system.h"
|
|
#include "doomtype.h"
|
|
#include "g_level.h"
|
|
#include "w_wad.h"
|
|
#include "r_state.h"
|
|
#include "r_utility.h"
|
|
#include "g_levellocals.h"
|
|
#include "textures/skyboxtexture.h"
|
|
|
|
#include "gl_load/gl_interface.h"
|
|
#include "gl/data/gl_vertexbuffer.h"
|
|
#include "gl/renderer/gl_lightdata.h"
|
|
#include "gl/renderer/gl_renderstate.h"
|
|
#include "gl/scene/gl_drawinfo.h"
|
|
#include "gl/scene/gl_scenedrawer.h"
|
|
#include "gl/shaders/gl_shader.h"
|
|
|
|
|
|
EXTERN_CVAR(Float, skyoffset)
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
FSkyVertexBuffer::FSkyVertexBuffer()
|
|
{
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
|
|
glBufferData(GL_ARRAY_BUFFER, mVertices.Size() * sizeof(FSkyVertex), &mVertices[0], GL_STATIC_DRAW);
|
|
}
|
|
|
|
void FSkyVertexBuffer::BindVBO()
|
|
{
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
|
|
glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FSkyVertex), &VSO->x);
|
|
glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FSkyVertex), &VSO->u);
|
|
glVertexAttribPointer(VATTR_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(FSkyVertex), &VSO->color);
|
|
glEnableVertexAttribArray(VATTR_VERTEX);
|
|
glEnableVertexAttribArray(VATTR_TEXCOORD);
|
|
glEnableVertexAttribArray(VATTR_COLOR);
|
|
glDisableVertexAttribArray(VATTR_VERTEX2);
|
|
glDisableVertexAttribArray(VATTR_NORMAL);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline void FSkyVertexBuffer::RenderRow(int prim, int row)
|
|
{
|
|
glDrawArrays(prim, mPrimStart[row], mPrimStart[row + 1] - mPrimStart[row]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FSkyVertexBuffer::RenderDome(FMaterial *tex, int mode)
|
|
{
|
|
int rc = mRows + 1;
|
|
|
|
// The caps only get drawn for the main layer but not for the overlay.
|
|
if (mode == SKYMODE_MAINLAYER && tex != NULL)
|
|
{
|
|
PalEntry pe = tex->tex->GetSkyCapColor(false);
|
|
gl_RenderState.SetObjectColor(pe);
|
|
gl_RenderState.EnableTexture(false);
|
|
gl_RenderState.Apply();
|
|
RenderRow(GL_TRIANGLE_FAN, 0);
|
|
|
|
pe = tex->tex->GetSkyCapColor(true);
|
|
gl_RenderState.SetObjectColor(pe);
|
|
gl_RenderState.Apply();
|
|
RenderRow(GL_TRIANGLE_FAN, rc);
|
|
gl_RenderState.EnableTexture(true);
|
|
}
|
|
gl_RenderState.SetObjectColor(0xffffffff);
|
|
gl_RenderState.Apply();
|
|
for (int i = 1; i <= mRows; i++)
|
|
{
|
|
RenderRow(GL_TRIANGLE_STRIP, i);
|
|
RenderRow(GL_TRIANGLE_STRIP, rc + i);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderDome(FMaterial * tex, float x_offset, float y_offset, bool mirror, int mode)
|
|
{
|
|
int texh = 0;
|
|
int texw = 0;
|
|
|
|
// 57 world units roughly represent one sky texel for the glTranslate call.
|
|
const float skyoffsetfactor = 57;
|
|
|
|
if (tex)
|
|
{
|
|
gl_RenderState.SetMaterial(tex, CLAMP_NONE, 0, -1, false);
|
|
texw = tex->TextureWidth();
|
|
texh = tex->TextureHeight();
|
|
gl_RenderState.EnableModelMatrix(true);
|
|
|
|
gl_RenderState.mModelMatrix.loadIdentity();
|
|
gl_RenderState.mModelMatrix.rotate(-180.0f + x_offset, 0.f, 1.f, 0.f);
|
|
|
|
float xscale = texw < 1024.f ? floor(1024.f / float(texw)) : 1.f;
|
|
float yscale = 1.f;
|
|
if (texh <= 128 && (level.flags & LEVEL_FORCETILEDSKY))
|
|
{
|
|
gl_RenderState.mModelMatrix.translate(0.f, (-40 + tex->tex->SkyOffset + skyoffset)*skyoffsetfactor, 0.f);
|
|
gl_RenderState.mModelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
|
|
yscale = 240.f / texh;
|
|
}
|
|
else if (texh < 128)
|
|
{
|
|
// smaller sky textures must be tiled. We restrict it to 128 sky pixels, though
|
|
gl_RenderState.mModelMatrix.translate(0.f, -1250.f, 0.f);
|
|
gl_RenderState.mModelMatrix.scale(1.f, 128 / 230.f, 1.f);
|
|
yscale = 128 / texh; // intentionally left as integer.
|
|
}
|
|
else if (texh < 200)
|
|
{
|
|
gl_RenderState.mModelMatrix.translate(0.f, -1250.f, 0.f);
|
|
gl_RenderState.mModelMatrix.scale(1.f, texh / 230.f, 1.f);
|
|
}
|
|
else if (texh <= 240)
|
|
{
|
|
gl_RenderState.mModelMatrix.translate(0.f, (200 - texh + tex->tex->SkyOffset + skyoffset)*skyoffsetfactor, 0.f);
|
|
gl_RenderState.mModelMatrix.scale(1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f, 1.f);
|
|
}
|
|
else
|
|
{
|
|
gl_RenderState.mModelMatrix.translate(0.f, (-40 + tex->tex->SkyOffset + skyoffset)*skyoffsetfactor, 0.f);
|
|
gl_RenderState.mModelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
|
|
yscale = 240.f / texh;
|
|
}
|
|
gl_RenderState.EnableTextureMatrix(true);
|
|
gl_RenderState.mTextureMatrix.loadIdentity();
|
|
gl_RenderState.mTextureMatrix.scale(mirror ? -xscale : xscale, yscale, 1.f);
|
|
gl_RenderState.mTextureMatrix.translate(1.f, y_offset / texh, 1.f);
|
|
}
|
|
|
|
GLRenderer->mSkyVBO->RenderDome(tex, mode);
|
|
gl_RenderState.EnableTextureMatrix(false);
|
|
gl_RenderState.EnableModelMatrix(false);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static void RenderBox(FTextureID texno, FMaterial * gltex, float x_offset, bool sky2)
|
|
{
|
|
FSkyBox * sb = static_cast<FSkyBox*>(gltex->tex);
|
|
int faces;
|
|
FMaterial * tex;
|
|
|
|
gl_RenderState.EnableModelMatrix(true);
|
|
gl_RenderState.mModelMatrix.loadIdentity();
|
|
|
|
if (!sky2)
|
|
gl_RenderState.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector.X, level.info->skyrotatevector.Z, level.info->skyrotatevector.Y);
|
|
else
|
|
gl_RenderState.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector2.X, level.info->skyrotatevector2.Z, level.info->skyrotatevector2.Y);
|
|
|
|
if (sb->faces[5])
|
|
{
|
|
faces=4;
|
|
|
|
// north
|
|
tex = FMaterial::ValidateTexture(sb->faces[0], false);
|
|
gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false);
|
|
gl_RenderState.Apply();
|
|
glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(0), 4);
|
|
|
|
// east
|
|
tex = FMaterial::ValidateTexture(sb->faces[1], false);
|
|
gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false);
|
|
gl_RenderState.Apply();
|
|
glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(1), 4);
|
|
|
|
// south
|
|
tex = FMaterial::ValidateTexture(sb->faces[2], false);
|
|
gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false);
|
|
gl_RenderState.Apply();
|
|
glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(2), 4);
|
|
|
|
// west
|
|
tex = FMaterial::ValidateTexture(sb->faces[3], false);
|
|
gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false);
|
|
gl_RenderState.Apply();
|
|
glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(3), 4);
|
|
}
|
|
else
|
|
{
|
|
faces=1;
|
|
tex = FMaterial::ValidateTexture(sb->faces[0], false);
|
|
gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false);
|
|
gl_RenderState.Apply();
|
|
glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(-1), 10);
|
|
}
|
|
|
|
// top
|
|
tex = FMaterial::ValidateTexture(sb->faces[faces], false);
|
|
gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false);
|
|
gl_RenderState.Apply();
|
|
glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(sb->fliptop? 6:5), 4);
|
|
|
|
// bottom
|
|
tex = FMaterial::ValidateTexture(sb->faces[faces+1], false);
|
|
gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false);
|
|
gl_RenderState.Apply();
|
|
glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(4), 4);
|
|
|
|
gl_RenderState.EnableModelMatrix(false);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void GLSkyPortal::DrawContents(FDrawInfo *di)
|
|
{
|
|
bool drawBoth = false;
|
|
|
|
// We have no use for Doom lighting special handling here, so disable it for this function.
|
|
int oldlightmode = ::level.lightmode;
|
|
if (::level.lightmode == 8)
|
|
{
|
|
::level.lightmode = 2;
|
|
gl_RenderState.SetSoftLightLevel(-1);
|
|
}
|
|
|
|
|
|
gl_RenderState.ResetColor();
|
|
gl_RenderState.EnableFog(false);
|
|
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
|
|
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
bool oldClamp = gl_RenderState.SetDepthClamp(true);
|
|
|
|
gl_MatrixStack.Push(gl_RenderState.mViewMatrix);
|
|
drawer->SetupView(0, 0, 0, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));
|
|
|
|
gl_RenderState.SetVertexBuffer(GLRenderer->mSkyVBO);
|
|
if (origin->texture[0] && origin->texture[0]->tex->bSkybox)
|
|
{
|
|
RenderBox(origin->skytexno1, origin->texture[0], origin->x_offset[0], origin->sky2);
|
|
}
|
|
else
|
|
{
|
|
if (origin->texture[0]==origin->texture[1] && origin->doublesky) origin->doublesky=false;
|
|
|
|
if (origin->texture[0])
|
|
{
|
|
gl_RenderState.SetTextureMode(TM_OPAQUE);
|
|
RenderDome(origin->texture[0], origin->x_offset[0], origin->y_offset, origin->mirrored, FSkyVertexBuffer::SKYMODE_MAINLAYER);
|
|
gl_RenderState.SetTextureMode(TM_MODULATE);
|
|
}
|
|
|
|
gl_RenderState.AlphaFunc(GL_GREATER, 0.f);
|
|
|
|
if (origin->doublesky && origin->texture[1])
|
|
{
|
|
RenderDome(origin->texture[1], origin->x_offset[1], origin->y_offset, false, FSkyVertexBuffer::SKYMODE_SECONDLAYER);
|
|
}
|
|
|
|
if (::level.skyfog>0 && !di->isFullbrightScene() && (origin->fadecolor & 0xffffff) != 0)
|
|
{
|
|
PalEntry FadeColor = origin->fadecolor;
|
|
FadeColor.a = clamp<int>(::level.skyfog, 0, 255);
|
|
|
|
gl_RenderState.EnableTexture(false);
|
|
gl_RenderState.SetObjectColor(FadeColor);
|
|
gl_RenderState.Apply();
|
|
glDrawArrays(GL_TRIANGLES, 0, 12);
|
|
gl_RenderState.EnableTexture(true);
|
|
gl_RenderState.SetObjectColor(0xffffffff);
|
|
}
|
|
}
|
|
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
|
|
gl_MatrixStack.Pop(gl_RenderState.mViewMatrix);
|
|
gl_RenderState.ApplyMatrices();
|
|
::level.lightmode = oldlightmode;
|
|
gl_RenderState.SetDepthClamp(oldClamp);
|
|
}
|
|
|