From f0a15febd1f5260d947565cbcf21082d3abbbd87 Mon Sep 17 00:00:00 2001 From: Ian Curtis Date: Sun, 9 Oct 2016 16:34:12 +0000 Subject: [PATCH] implement scroll fog, fixes a tonne of missing fx --- Src/Graphics/New3D/New3D.cpp | 24 +++++-- Src/Graphics/New3D/New3D.h | 3 + Src/Graphics/New3D/R3DScrollFog.cpp | 104 ++++++++++++++++++++++++++++ Src/Graphics/New3D/R3DScrollFog.h | 54 +++++++++++++++ VS2008/Supermodel.vcxproj | 2 + VS2008/Supermodel.vcxproj.filters | 6 ++ 6 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 Src/Graphics/New3D/R3DScrollFog.cpp create mode 100644 Src/Graphics/New3D/R3DScrollFog.h diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index f17d0bb..c8bebac 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -81,6 +81,20 @@ void CNew3D::UploadTextures(unsigned x, unsigned y, unsigned width, unsigned hei m_texSheet.Invalidate(x, y, width, height); } +void CNew3D::DrawScrollFog() +{ + for (auto &n : m_nodes) { + + if (n.viewport.scrollFog > 0) { + + float *rgb = n.viewport.fogParams; + m_r3dScrollFog.DrawScrollFog(rgb[0], rgb[1], rgb[2], n.viewport.scrollFog); + + return; // only allowed once per frame? + } + } +} + void CNew3D::RenderScene(int priority, bool alpha) { if (alpha) { @@ -178,6 +192,10 @@ void CNew3D::RenderFrame(void) m_modelMat.Release(); // would hope we wouldn't need this but no harm in checking m_nodeAttribs.Reset(); + RenderViewport(0x800000); // build model structure + + DrawScrollFog(); // fog layer if applicable must be drawn here + glDepthFunc (GL_LEQUAL); glEnable (GL_DEPTH_TEST); glActiveTexture (GL_TEXTURE0); @@ -185,10 +203,8 @@ void CNew3D::RenderFrame(void) glFrontFace (GL_CW); glStencilFunc (GL_EQUAL, 0, 0xFF); // basically stencil test passes if the value is zero - glStencilOp (GL_KEEP, GL_INCR, GL_INCR); // if the stencil test passes, we incriment the value + glStencilOp (GL_KEEP, GL_INCR, GL_INCR); // if the stencil test passes, we incriment the value glStencilMask (0xFF); - - RenderViewport(0x800000); // build model structure m_vbo.Bind(true); m_vbo.BufferSubData(MAX_ROM_POLYS*sizeof(Poly), m_polyBufferRam.size()*sizeof(Poly), m_polyBufferRam.data()); // upload all the dynamic data to GPU in one go @@ -224,7 +240,7 @@ void CNew3D::RenderFrame(void) glNormalPointer (GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, normal)); glTexCoordPointer (2, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, texcoords)); glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(Vertex), (void*)offsetof(Vertex, color)); - + m_r3dShader.SetShader(true); for (int pri = 0; pri <= 3; pri++) { diff --git a/Src/Graphics/New3D/New3D.h b/Src/Graphics/New3D/New3D.h index f5e3737..c25e0e0 100644 --- a/Src/Graphics/New3D/New3D.h +++ b/Src/Graphics/New3D/New3D.h @@ -39,6 +39,7 @@ #include "R3DData.h" #include "Plane.h" #include "Vec.h" +#include "R3DScrollFog.h" namespace New3D { @@ -177,6 +178,7 @@ private: float Determinant3x3(const float m[16]); bool IsDynamicModel(UINT32 *data); // check if the model has a colour palette bool IsVROMModel(UINT32 modelAddr); + void DrawScrollFog(); void CalcTexOffset(int offX, int offY, int page, int x, int y, int& newX, int& newY); @@ -216,6 +218,7 @@ private: VBO m_vbo; // large VBO to hold our poly data, start of VBO is ROM data, ram polys follow R3DShader m_r3dShader; + R3DScrollFog m_r3dScrollFog; Plane m_planes[6]; diff --git a/Src/Graphics/New3D/R3DScrollFog.cpp b/Src/Graphics/New3D/R3DScrollFog.cpp new file mode 100644 index 0000000..e926bab --- /dev/null +++ b/Src/Graphics/New3D/R3DScrollFog.cpp @@ -0,0 +1,104 @@ +#include "R3DScrollFog.h" +#include "Graphics/Shader.h" +#include "Mat4.h" + +namespace New3D { + +static const char *vertexShaderFog = + + "uniform mat4 mvp;\n" + + "void main(void)\n" + "{\n" + "gl_Position = mvp * gl_Vertex;\n" + "}\n"; + +static const char *fragmentShaderFog = + + "uniform vec4 fogColour;\n" + + "void main()\n" + "{\n" + "gl_FragColor = fogColour;\n" + "}\n"; + + +R3DScrollFog::R3DScrollFog() +{ + //default coordinates are NDC -1,1 etc + + m_triangles[0].p1.Set(-1,-1, 0); + m_triangles[0].p2.Set(-1, 1, 0); + m_triangles[0].p3.Set( 1, 1, 0); + + m_triangles[1].p1.Set(-1,-1, 0); + m_triangles[1].p2.Set( 1, 1, 0); + m_triangles[1].p3.Set( 1,-1, 0); + + m_shaderProgram = 0; + m_vertexShader = 0; + m_fragmentShader = 0; + + AllocResources(); +} + +R3DScrollFog::~R3DScrollFog() +{ + DeallocResources(); +} + +void R3DScrollFog::DrawScrollFog(float r, float g, float b, float a) +{ + //======= + Mat4 mvp; + //======= + + // yeah this would have been much easier with immediate mode and fixed function .. >_< + + // some ogl states + glDepthMask (GL_FALSE); // disable z writes + glDisable (GL_DEPTH_TEST); // disable depth testing + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + m_vbo.Bind (true); + glUseProgram (m_shaderProgram); + glUniform4f (m_locFogColour, r, g, b, a); + glUniformMatrix4fv (m_locMVP, 1, GL_FALSE, mvp); + + glEnableClientState (GL_VERTEX_ARRAY); + glVertexPointer (3, GL_FLOAT, sizeof(SFVertex), 0); + glDrawArrays (GL_TRIANGLES, 0, 6); + glDisableClientState(GL_VERTEX_ARRAY); + + glUseProgram (0); + m_vbo.Bind (false); + + glDisable (GL_BLEND); + glDepthMask (GL_TRUE); +} + +void R3DScrollFog::AllocResources() +{ + bool success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, nullptr, nullptr, vertexShaderFog, fragmentShaderFog); + + m_locMVP = glGetUniformLocation(m_shaderProgram, "mvp"); + m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour"); + + m_vbo.Create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, sizeof(SFTriangle) * (2), m_triangles); +} + +void R3DScrollFog::DeallocResources() +{ + if (m_shaderProgram) { + DestroyShaderProgram(m_shaderProgram, m_vertexShader, m_fragmentShader); + } + + m_shaderProgram = 0; + m_vertexShader = 0; + m_fragmentShader = 0; + + m_vbo.Destroy(); +} + +} \ No newline at end of file diff --git a/Src/Graphics/New3D/R3DScrollFog.h b/Src/Graphics/New3D/R3DScrollFog.h new file mode 100644 index 0000000..893607f --- /dev/null +++ b/Src/Graphics/New3D/R3DScrollFog.h @@ -0,0 +1,54 @@ +#ifndef _R3DSCROLLFOG_H_ +#define _R3DSCROLLFOG_H_ + +#include "VBO.h" + +namespace New3D { + +class R3DScrollFog +{ +public: + + R3DScrollFog(); + ~R3DScrollFog(); + + void DrawScrollFog(float r, float g, float b, float a); + +private: + + void AllocResources(); + void DeallocResources(); + + struct SFVertex + { + void Set(float x, float y, float z) { + v[0] = x; + v[1] = y; + v[2] = z; + } + + float v[3]; + }; + + struct SFTriangle + { + SFVertex p1; + SFVertex p2; + SFVertex p3; + }; + + SFTriangle m_triangles[2]; + + GLuint m_shaderProgram; + GLuint m_vertexShader; + GLuint m_fragmentShader; + + GLuint m_locFogColour; + GLuint m_locMVP; + + VBO m_vbo; +}; + +} + +#endif \ No newline at end of file diff --git a/VS2008/Supermodel.vcxproj b/VS2008/Supermodel.vcxproj index 57c4e80..72e50e9 100644 --- a/VS2008/Supermodel.vcxproj +++ b/VS2008/Supermodel.vcxproj @@ -317,6 +317,7 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi + @@ -542,6 +543,7 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi + diff --git a/VS2008/Supermodel.vcxproj.filters b/VS2008/Supermodel.vcxproj.filters index 52d7e5e..17ec876 100644 --- a/VS2008/Supermodel.vcxproj.filters +++ b/VS2008/Supermodel.vcxproj.filters @@ -434,6 +434,9 @@ Source Files\OSD + + Source Files\Graphics\New + @@ -802,6 +805,9 @@ Header Files\Pkgs + + Source Files\Graphics\New +