From 175b697ba2ae4e3a1a31b906ead7d5c4170b8580 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 24 Mar 2020 17:49:21 +0100 Subject: [PATCH] Implement warp effect --- .../polyrenderer/backend/poly_renderstate.cpp | 5 +++ .../drawers/screen_scanline_setup.cpp | 44 ++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 0ee16f47d..1d19460ec 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -280,6 +280,11 @@ void PolyRenderState::Apply() mDrawCommands->SetShader(EFF_NONE, mTextureEnabled ? effectState : SHADER_NoTexture, mAlphaThreshold >= 0.f, false); } + if (mMaterial.mMaterial && mMaterial.mMaterial->tex) + mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->tex->shaderspeed / 1000.); + else + mStreamData.timer = 0.0f; + PolyPushConstants constants; constants.uFogEnabled = fogset; constants.uTextureMode = mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode; diff --git a/src/rendering/polyrenderer/drawers/screen_scanline_setup.cpp b/src/rendering/polyrenderer/drawers/screen_scanline_setup.cpp index e4fa51a6a..ba95a06f4 100644 --- a/src/rendering/polyrenderer/drawers/screen_scanline_setup.cpp +++ b/src/rendering/polyrenderer/drawers/screen_scanline_setup.cpp @@ -407,6 +407,33 @@ static void WriteVaryingWrap(float pos, float step, int x0, int x1, const float* } #endif +static void WriteVaryingWarp1(float posU, float posV, float stepU, float stepV, int x0, int x1, PolyTriangleThreadData* thread) +{ + float pi2 = 3.14159265358979323846f * 2.0f; + float timer = thread->mainVertexShader.Data.timer * 0.125f; + + const float* w = thread->scanline.W; + uint16_t* scanlineU = thread->scanline.U; + uint16_t* scanlineV = thread->scanline.V; + + for (int x = x0; x < x1; x++) + { + float u = posU * w[x]; + float v = posV * w[x]; + + v += sin(pi2 * (u + timer)) * 0.1f; + u += sin(pi2 * (v + timer)) * 0.1f; + + u = u - std::floor(u); + v = v - std::floor(v); + scanlineU[x] = static_cast(static_cast(u * static_cast(0x1000'0000)) << 4) >> 16; + scanlineV[x] = static_cast(static_cast(v * static_cast(0x1000'0000)) << 4) >> 16; + + posU += stepU; + posV += stepV; + } +} + #ifdef NO_SSE static void WriteVaryingColor(float pos, float step, int x0, int x1, const float* w, uint8_t* varying) { @@ -448,8 +475,21 @@ void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyT float startX = x0 + (0.5f - args->v1->x); float startY = y + (0.5f - args->v1->y); - WriteVaryingWrap(args->v1->u * args->v1->w + args->gradientX.U * startX + args->gradientY.U * startY, args->gradientX.U, x0, x1, thread->scanline.W, thread->scanline.U); - WriteVaryingWrap(args->v1->v * args->v1->w + args->gradientX.V * startX + args->gradientY.V * startY, args->gradientX.V, x0, x1, thread->scanline.W, thread->scanline.V); + if (thread->EffectState == SHADER_Warp1 || thread->EffectState == SHADER_Warp2) + { + WriteVaryingWarp1( + args->v1->u * args->v1->w + args->gradientX.U * startX + args->gradientY.U * startY, + args->v1->v * args->v1->w + args->gradientX.V * startX + args->gradientY.V * startY, + args->gradientX.U, + args->gradientX.V, + x0, x1, + thread); + } + else + { + WriteVaryingWrap(args->v1->u * args->v1->w + args->gradientX.U * startX + args->gradientY.U * startY, args->gradientX.U, x0, x1, thread->scanline.W, thread->scanline.U); + WriteVaryingWrap(args->v1->v * args->v1->w + args->gradientX.V * startX + args->gradientY.V * startY, args->gradientX.V, x0, x1, thread->scanline.W, thread->scanline.V); + } WriteVarying(args->v1->worldX * args->v1->w + args->gradientX.WorldX * startX + args->gradientY.WorldX * startY, args->gradientX.WorldX, x0, x1, thread->scanline.W, thread->scanline.WorldX); WriteVarying(args->v1->worldY * args->v1->w + args->gradientX.WorldY * startX + args->gradientY.WorldY * startY, args->gradientX.WorldY, x0, x1, thread->scanline.W, thread->scanline.WorldY); WriteVarying(args->v1->worldZ * args->v1->w + args->gradientX.WorldZ * startX + args->gradientY.WorldZ * startY, args->gradientX.WorldZ, x0, x1, thread->scanline.W, thread->scanline.WorldZ);