diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c74c9534d..03f3372f0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1061,6 +1061,7 @@ set( FASTMATH_SOURCES gl/utility/gl_cycler.cpp gl/utility/gl_geometric.cpp gl/renderer/gl_2ddrawer.cpp + gl/renderer/gl_quaddrawer.cpp gl/renderer/gl_renderer.cpp gl/renderer/gl_renderstate.cpp gl/renderer/gl_renderbuffers.cpp diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index 4d2252fe0..c9abae0da 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -97,9 +97,17 @@ public: { return &map[mCurIndex]; } + FFlatVertex *Alloc(int num, int *poffset) + { + FFlatVertex *p = GetBuffer(); + *poffset = mCurIndex; + mCurIndex += num; + if (mCurIndex >= BUFFER_SIZE_TO_USE) mCurIndex = mIndex; + return p; + } + unsigned int GetCount(FFlatVertex *newptr, unsigned int *poffset) { - unsigned int newofs = (unsigned int)(newptr - map); unsigned int diff = newofs - mCurIndex; *poffset = mCurIndex; diff --git a/src/gl/renderer/gl_quaddrawer.cpp b/src/gl/renderer/gl_quaddrawer.cpp new file mode 100644 index 000000000..b80f123e0 --- /dev/null +++ b/src/gl/renderer/gl_quaddrawer.cpp @@ -0,0 +1,85 @@ +/* +** gl_quaddrawer.h +** +**--------------------------------------------------------------------------- +** Copyright 2016 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be +** covered by the terms of the GNU Lesser General Public License as published +** by the Free Software Foundation; either version 2.1 of the License, or (at +** your option) any later version. +** 5. Full disclosure of the entire project's source code, except for third +** party libraries is mandatory. (NOTE: This clause is non-negotiable!) +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "gl/system/gl_system.h" +#include "gl/shaders/gl_shader.h" +#include "gl/renderer/gl_renderer.h" +#include "gl/renderer/gl_renderstate.h" +#include "gl/renderer/gl_quaddrawer.h" +#include "gl/data/gl_matrix.h" + +/* +** For handling of dynamically created quads when no persistently mapped +** buffer or client array is available (i.e. GL 3.x core profiles) +** +** In this situation the 4 vertices of a quad primitive are being passed +** as a matrix uniform because that is a lot faster than any kind of +** temporary buffer change. +*/ + +FFlatVertex FQuadDrawer::buffer[4]; + +//========================================================================== +// +// +// +//========================================================================== + +void FQuadDrawer::DoRender(int type) +{ + // When this gets called, the render state must already be applied so we can just + // send our vertices to the current shader. + float matV[16], matT[16]; + + for(int i=0;i<4;i++) + { + matV[i*4+0] = buffer[i].x; + matV[i*4+1] = buffer[i].z; + matV[i*4+2] = buffer[i].y; + matT[i*4+0] = buffer[i].u; + matT[i*4+1] = buffer[i].v; + matV[i*4+3] = matT[i*4+2] = matT[i*4+3] = 0; + } + FShader *shader = GLRenderer->mShaderManager->GetActiveShader(); + glUniformMatrix4fv(shader->vertexmatrix_index, 1, false, matV); + glUniformMatrix4fv(shader->texcoordmatrix_index, 1, false, matT); + glUniform1i(shader->quadmode_index, 1); + GLRenderer->mVBO->RenderArray(type, 0, 4); + glUniform1i(shader->quadmode_index, 0); +} diff --git a/src/gl/renderer/gl_quaddrawer.h b/src/gl/renderer/gl_quaddrawer.h new file mode 100644 index 000000000..3fcca65c2 --- /dev/null +++ b/src/gl/renderer/gl_quaddrawer.h @@ -0,0 +1,44 @@ +#ifndef __QDRAWER_H +#define __QDRAWER_H + +#include "gl/data/gl_vertexbuffer.h" + +class FQuadDrawer +{ + FFlatVertex *p; + int ndx; + static FFlatVertex buffer[4]; + + void DoRender(int type); +public: + + FQuadDrawer() + { + if (gl.flags & RFL_QUADHACK) + { + p = buffer; + } + else + { + p = GLRenderer->mVBO->Alloc(4, &ndx); + } + } + void Set(int ndx, float x, float y, float z, float s, float t) + { + p[ndx].Set(x, y, z, s, t); + } + void Render(int type) + { + if (gl.flags & RFL_QUADHACK) + { + DoRender(type); + } + else + { + GLRenderer->mVBO->RenderArray(type, ndx, 4); + } + } +}; + + +#endif diff --git a/src/gl/scene/gl_decal.cpp b/src/gl/scene/gl_decal.cpp index 1a10b3f4d..c9de15144 100644 --- a/src/gl/scene/gl_decal.cpp +++ b/src/gl/scene/gl_decal.cpp @@ -54,6 +54,7 @@ #include "gl/textures/gl_texture.h" #include "gl/textures/gl_material.h" #include "gl/utility/gl_clock.h" +#include "gl/renderer/gl_quaddrawer.h" struct DecalVertex { @@ -328,22 +329,19 @@ void GLWall::DrawDecal(DBaseDecal *decal) gl_RenderState.SetFog(0,-1); } - FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); + FQuadDrawer qd; for (i = 0; i < 4; i++) { - ptr->Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v); - ptr++; + qd.Set(i, dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v); } if (lightlist == NULL) { gl_RenderState.Apply(); - GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); + qd.Render(GL_TRIANGLE_FAN); } else { - unsigned int offset; - unsigned int count = GLRenderer->mVBO->GetCount(ptr, &offset); for (unsigned k = 0; k < lightlist->Size(); k++) { secplane_t &lowplane = k == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[k + 1].plane; @@ -363,7 +361,7 @@ void GLWall::DrawDecal(DBaseDecal *decal) gl_RenderState.SetSplitPlanes((*lightlist)[k].plane, lowplane); gl_RenderState.Apply(); - GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, offset, count); + qd.Render(GL_TRIANGLE_FAN); } if (low1 <= dv[0].z && low2 <= dv[3].z) break; } diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 0dc8efd84..1d3936948 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -57,6 +57,7 @@ #include "gl/utility/gl_templates.h" #include "gl/shaders/gl_shader.h" #include "gl/stereo3d/scoped_color_mask.h" +#include "gl/renderer/gl_quaddrawer.h" FDrawInfo * gl_drawinfo; @@ -1079,17 +1080,12 @@ void FDrawInfo::SetupFloodStencil(wallseg * ws) glDepthMask(true); gl_RenderState.Apply(); - FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); - ptr->Set(ws->x1, ws->z1, ws->y1, 0, 0); - ptr++; - ptr->Set(ws->x1, ws->z2, ws->y1, 0, 0); - ptr++; - ptr->Set(ws->x2, ws->z2, ws->y2, 0, 0); - ptr++; - ptr->Set(ws->x2, ws->z1, ws->y2, 0, 0); - ptr++; - GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); - + FQuadDrawer qd; + qd.Set(0, ws->x1, ws->z1, ws->y1, 0, 0); + qd.Set(1, ws->x1, ws->z2, ws->y1, 0, 0); + qd.Set(2, ws->x2, ws->z2, ws->y2, 0, 0); + qd.Set(3, ws->x2, ws->z1, ws->y2, 0, 0); + qd.Render(GL_TRIANGLE_FAN); glStencilFunc(GL_EQUAL, recursion + 1, ~0); // draw sky into stencil glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil @@ -1112,16 +1108,12 @@ void FDrawInfo::ClearFloodStencil(wallseg * ws) gl_RenderState.ResetColor(); gl_RenderState.Apply(); - FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); - ptr->Set(ws->x1, ws->z1, ws->y1, 0, 0); - ptr++; - ptr->Set(ws->x1, ws->z2, ws->y1, 0, 0); - ptr++; - ptr->Set(ws->x2, ws->z2, ws->y2, 0, 0); - ptr++; - ptr->Set(ws->x2, ws->z1, ws->y2, 0, 0); - ptr++; - GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); + FQuadDrawer qd; + qd.Set(0, ws->x1, ws->z1, ws->y1, 0, 0); + qd.Set(1, ws->x1, ws->z2, ws->y1, 0, 0); + qd.Set(2, ws->x2, ws->z2, ws->y2, 0, 0); + qd.Set(3, ws->x2, ws->z1, ws->y2, 0, 0); + qd.Render(GL_TRIANGLE_FAN); // restore old stencil op. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -1192,16 +1184,12 @@ void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, boo float px4 = fviewx + prj_fac1 * (ws->x2-fviewx); float py4 = fviewy + prj_fac1 * (ws->y2-fviewy); - FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); - ptr->Set(px1, planez, py1, px1 / 64, -py1 / 64); - ptr++; - ptr->Set(px2, planez, py2, px2 / 64, -py2 / 64); - ptr++; - ptr->Set(px3, planez, py3, px3 / 64, -py3 / 64); - ptr++; - ptr->Set(px4, planez, py4, px4 / 64, -py4 / 64); - ptr++; - GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); + FQuadDrawer qd; + qd.Set(0, px1, planez, py1, px1 / 64, -py1 / 64); + qd.Set(1, px2, planez, py2, px2 / 64, -py2 / 64); + qd.Set(2, px3, planez, py3, px3 / 64, -py3 / 64); + qd.Set(3, px4, planez, py4, px4 / 64, -py4 / 64); + qd.Render(GL_TRIANGLE_FAN); gl_RenderState.EnableTextureMatrix(false); } diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 76796adf9..3dff0f32a 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -64,6 +64,7 @@ #include "gl/textures/gl_material.h" #include "gl/utility/gl_clock.h" #include "gl/data/gl_vertexbuffer.h" +#include "gl/renderer/gl_quaddrawer.h" CVAR(Bool, gl_usecolorblending, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, gl_spritebrightfog, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); @@ -400,17 +401,12 @@ void GLSprite::Draw(int pass) } FFlatVertex *ptr; - unsigned int offset, count; - ptr = GLRenderer->mVBO->GetBuffer(); - ptr->Set(v1[0], v1[1], v1[2], ul, vt); - ptr++; - ptr->Set(v2[0], v2[1], v2[2], ur, vt); - ptr++; - ptr->Set(v3[0], v3[1], v3[2], ul, vb); - ptr++; - ptr->Set(v4[0], v4[1], v4[2], ur, vb); - ptr++; - GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP, &offset, &count); + FQuadDrawer qd; + qd.Set(0, v1[0], v1[1], v1[2], ul, vt); + qd.Set(1, v2[0], v2[1], v2[2], ur, vt); + qd.Set(2, v3[0], v3[1], v3[2], ul, vb); + qd.Set(3, v4[0], v4[1], v4[2], ur, vb); + qd.Render(GL_TRIANGLE_STRIP); if (foglayer) { @@ -420,7 +416,7 @@ void GLSprite::Draw(int pass) gl_RenderState.BlendEquation(GL_FUNC_ADD); gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.Apply(); - GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, offset, count); + qd.Render(GL_TRIANGLE_STRIP); gl_RenderState.SetFixedColormap(CM_DEFAULT); } } diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 34779ec7c..598254c10 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -57,6 +57,7 @@ #include "gl/models/gl_models.h" #include "gl/shaders/gl_shader.h" #include "gl/textures/gl_material.h" +#include "gl/renderer/gl_quaddrawer.h" EXTERN_CVAR (Bool, r_drawplayersprites) EXTERN_CVAR(Float, transsouls) @@ -161,16 +162,12 @@ void FGLRenderer::DrawPSprite (player_t * player,DPSprite *psp, float sx, float gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); } gl_RenderState.Apply(); - FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); - ptr->Set(x1, y1, 0, fU1, fV1); - ptr++; - ptr->Set(x1, y2, 0, fU1, fV2); - ptr++; - ptr->Set(x2, y1, 0, fU2, fV1); - ptr++; - ptr->Set(x2, y2, 0, fU2, fV2); - ptr++; - GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); + FQuadDrawer qd; + qd.Set(0, x1, y1, 0, fU1, fV1); + qd.Set(1, x1, y2, 0, fU1, fV2); + qd.Set(2, x2, y1, 0, fU2, fV1); + qd.Set(3, x2, y2, 0, fU2, fV2); + qd.Render(GL_TRIANGLE_STRIP); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f); } diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index d0cc5ef3f..c3f0f83da 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -265,6 +265,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * viewmatrix_index = glGetUniformLocation(hShader, "ViewMatrix"); modelmatrix_index = glGetUniformLocation(hShader, "ModelMatrix"); texturematrix_index = glGetUniformLocation(hShader, "TextureMatrix"); + vertexmatrix_index = glGetUniformLocation(hShader, "uQuadVertices"); + texcoordmatrix_index = glGetUniformLocation(hShader, "uQuadTexCoords"); + quadmode_index = glGetUniformLocation(hShader, "uQuadMode"); if (LM_SOFTWARE != gl.lightmethod && !(gl.flags & RFL_SHADER_STORAGE_BUFFER)) { diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index a0b01d20d..75e4b4e5e 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -244,6 +244,9 @@ class FShader int modelmatrix_index; int texturematrix_index; public: + int vertexmatrix_index; + int texcoordmatrix_index; + int quadmode_index; int fakevb_index; private: int currentglowstate = 0; diff --git a/src/gl/system/gl_interface.h b/src/gl/system/gl_interface.h index 11b0573e5..9eca673f5 100644 --- a/src/gl/system/gl_interface.h +++ b/src/gl/system/gl_interface.h @@ -25,7 +25,8 @@ enum RenderFlags RFL_NO_DEPTHSTENCIL = 64, RFL_NO_CLIP_PLANES = 128, - RFL_INVALIDATE_BUFFER = 256 + RFL_INVALIDATE_BUFFER = 256, + RFL_QUADHACK = 512 }; enum TexMode diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index 7cc4d4d83..281c509d3 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -13,10 +13,28 @@ out vec4 vColor; void main() { - #ifndef SIMPLE - vec4 worldcoord = ModelMatrix * mix(aPosition, aVertex2, uInterpolationFactor); + vec2 parmTexCoord; + vec4 parmPosition; + #ifndef USE_QUAD_DRAWER + parmTexCoord = aTexCoord; + parmPosition = aPosition; #else - vec4 worldcoord = ModelMatrix * aPosition; + if (uQuadMode == 0) + { + parmTexCoord = aTexCoord; + parmPosition = aPosition; + } + else + { + parmPosition = uQuadVertices[int(aPosition.x)].st; + parmTexCoord = uQuadTexCoords[int(aPosition.x)]; + } + #endif + + #ifndef SIMPLE + vec4 worldcoord = ModelMatrix * mix(parmPosition, aVertex2, uInterpolationFactor); + #else + vec4 worldcoord = ModelMatrix * parmPosition; #endif vec4 eyeCoordPos = ViewMatrix * worldcoord; @@ -39,13 +57,13 @@ void main() #ifdef SPHEREMAP vec3 u = normalize(eyeCoordPos.xyz); - vec4 n = normalize(TextureMatrix * vec4(aTexCoord.x, 0.0, aTexCoord.y, 0.0)); // use texture matrix and coordinates for our normal. Since this is only used on walls, the normal's y coordinate is always 0. + vec4 n = normalize(TextureMatrix * vec4(parmTexCoord.x, 0.0, parmTexCoord.y, 0.0)); // use texture matrix and coordinates for our normal. Since this is only used on walls, the normal's y coordinate is always 0. vec3 r = reflect(u, n.xyz); float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) ); vec2 sst = vec2(r.x/m + 0.5, r.y/m + 0.5); vTexCoord.xy = sst; #else - vTexCoord = TextureMatrix * vec4(aTexCoord, 0.0, 1.0); + vTexCoord = TextureMatrix * vec4(parmTexCoord, 0.0, 1.0); #endif gl_Position = ProjectionMatrix * eyeCoordPos; diff --git a/wadsrc/static/shaders/glsl/shaderdefs.i b/wadsrc/static/shaders/glsl/shaderdefs.i index 7500a0cfc..3701694bc 100644 --- a/wadsrc/static/shaders/glsl/shaderdefs.i +++ b/wadsrc/static/shaders/glsl/shaderdefs.i @@ -45,6 +45,13 @@ uniform int uFogEnabled; // dynamic lights uniform int uLightIndex; +// quad drawer stuff +#ifdef USE_QUAD_DRAWER +uniform mat4 uQuadVertices; +uniform mat4 uQuadTexCoords; +uniform int uQuadMode; +#endif + // matrices uniform mat4 ProjectionMatrix; uniform mat4 ViewMatrix;