void GLSoftSpriteRenderer::Render() { SPADES_MARK_FUNCTION(); lastImage = NULL; program->Use(); device->Enable(IGLDevice::Blend, true); device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); projectionViewMatrix(program); rightVector(program); frontVector(program); viewOriginVector(program); upVector(program); texture(program); depthTexture(program); viewMatrix(program); fogDistance(program); fogColor(program); zNearFar(program); positionAttribute(program); spritePosAttribute(program); colorAttribute(program); projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); viewMatrix.SetValue(renderer->GetViewMatrix()); fogDistance.SetValue(renderer->GetFogDistance()); Vector3 fogCol = renderer->GetFogColor(); fogCol *= fogCol; // linearize fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); const client::SceneDefinition &def = renderer->GetSceneDef(); rightVector.SetValue(def.viewAxis[0].x, def.viewAxis[0].y, def.viewAxis[0].z); upVector.SetValue(def.viewAxis[1].x, def.viewAxis[1].y, def.viewAxis[1].z); frontVector.SetValue(def.viewAxis[2].x, def.viewAxis[2].y, def.viewAxis[2].z); viewOriginVector.SetValue(def.viewOrigin.x, def.viewOrigin.y, def.viewOrigin.z); texture.SetValue(0); depthTexture.SetValue(1); zNearFar.SetValue(def.zNear, def.zFar); device->ActiveTexture(1); device->BindTexture(IGLDevice::Texture2D, renderer->GetFramebufferManager()->GetDepthTexture()); device->ActiveTexture(0); device->EnableVertexAttribArray(positionAttribute(), true); device->EnableVertexAttribArray(spritePosAttribute(), true); device->EnableVertexAttribArray(colorAttribute(), true); thresLow = tanf(def.fovX * .5f) * tanf(def.fovY * .5f) * 1.8f; thresRange = thresLow * .5f; // full-resolution sprites { GLProfiler::Context measure(renderer->GetGLProfiler(), "Full Resolution"); for (size_t i = 0; i < sprites.size(); i++) { Sprite &spr = sprites[i]; float layer = LayerForSprite(spr); if (layer == 1.f) continue; if (spr.image != lastImage) { Flush(); lastImage = spr.image; SPAssert(vertices.empty()); } Vertex v; v.x = spr.center.x; v.y = spr.center.y; v.z = spr.center.z; v.radius = spr.radius; v.angle = spr.angle; v.r = spr.color.x; v.g = spr.color.y; v.b = spr.color.z; v.a = spr.color.w; float fade = 1.f - layer; v.r *= fade; v.g *= fade; v.b *= fade; v.a *= fade; uint32_t idx = (uint32_t)vertices.size(); v.sx = -1; v.sy = -1; vertices.push_back(v); v.sx = 1; v.sy = -1; vertices.push_back(v); v.sx = -1; v.sy = 1; vertices.push_back(v); v.sx = 1; v.sy = 1; vertices.push_back(v); indices.push_back(idx); indices.push_back(idx + 1); indices.push_back(idx + 2); indices.push_back(idx + 1); indices.push_back(idx + 3); indices.push_back(idx + 2); } Flush(); } // low-res sprites IGLDevice::UInteger lastFb = device->GetInteger(IGLDevice::FramebufferBinding); int sW = device->ScreenWidth(), sH = device->ScreenHeight(); int lW = (sW + 3) / 4, lH = (sH + 3) / 4; int numLowResSprites = 0; GLColorBuffer buf = renderer->GetFramebufferManager()->CreateBufferHandle(lW, lH, true); device->BindFramebuffer(IGLDevice::Framebuffer, buf.GetFramebuffer()); device->ClearColor(0.f, 0.f, 0.f, 0.f); device->Clear(IGLDevice::ColorBufferBit); device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); device->Viewport(0, 0, lW, lH); { GLProfiler::Context measure(renderer->GetGLProfiler(), "Low Resolution"); for (size_t i = 0; i < sprites.size(); i++) { Sprite &spr = sprites[i]; float layer = LayerForSprite(spr); if (layer == 0.f) continue; if (spr.image != lastImage) { Flush(); lastImage = spr.image; SPAssert(vertices.empty()); } numLowResSprites++; Vertex v; v.x = spr.center.x; v.y = spr.center.y; v.z = spr.center.z; v.radius = spr.radius; v.angle = spr.angle; v.r = spr.color.x; v.g = spr.color.y; v.b = spr.color.z; v.a = spr.color.w; float fade = layer; v.r *= fade; v.g *= fade; v.b *= fade; v.a *= fade; uint32_t idx = (uint32_t)vertices.size(); v.sx = -1; v.sy = -1; vertices.push_back(v); v.sx = 1; v.sy = -1; vertices.push_back(v); v.sx = -1; v.sy = 1; vertices.push_back(v); v.sx = 1; v.sy = 1; vertices.push_back(v); indices.push_back(idx); indices.push_back(idx + 1); indices.push_back(idx + 2); indices.push_back(idx + 1); indices.push_back(idx + 3); indices.push_back(idx + 2); } Flush(); } // finalize device->ActiveTexture(1); device->BindTexture(IGLDevice::Texture2D, 0); device->ActiveTexture(0); device->BindTexture(IGLDevice::Texture2D, 0); device->EnableVertexAttribArray(positionAttribute(), false); device->EnableVertexAttribArray(spritePosAttribute(), false); device->EnableVertexAttribArray(colorAttribute(), false); // composite downsampled sprite device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); if (numLowResSprites > 0) { GLProfiler::Context measure(renderer->GetGLProfiler(), "Finalize"); GLQuadRenderer qr(device); // do gaussian blur GLProgram *program = renderer->RegisterProgram("Shaders/PostFilters/Gauss1D.program"); static GLProgramAttribute blur_positionAttribute("positionAttribute"); static GLProgramUniform blur_textureUniform("mainTexture"); static GLProgramUniform blur_unitShift("unitShift"); program->Use(); blur_positionAttribute(program); blur_textureUniform(program); blur_unitShift(program); blur_textureUniform.SetValue(0); device->ActiveTexture(0); qr.SetCoordAttributeIndex(blur_positionAttribute()); device->Enable(IGLDevice::Blend, false); // x-direction GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle(lW, lH, true); device->BindTexture(IGLDevice::Texture2D, buf.GetTexture()); device->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); blur_unitShift.SetValue(1.f / lW, 0.f); qr.Draw(); buf.Release(); // x-direction GLColorBuffer buf3 = renderer->GetFramebufferManager()->CreateBufferHandle(lW, lH, true); device->BindTexture(IGLDevice::Texture2D, buf2.GetTexture()); device->BindFramebuffer(IGLDevice::Framebuffer, buf3.GetFramebuffer()); blur_unitShift.SetValue(0.f, 1.f / lH); qr.Draw(); buf2.Release(); buf = buf3; device->Enable(IGLDevice::Blend, true); // composite program = renderer->RegisterProgram("Shaders/PostFilters/PassThrough.program"); static GLProgramAttribute positionAttribute("positionAttribute"); static GLProgramUniform colorUniform("colorUniform"); static GLProgramUniform textureUniform("mainTexture"); static GLProgramUniform texCoordRange("texCoordRange"); positionAttribute(program); textureUniform(program); texCoordRange(program); colorUniform(program); program->Use(); textureUniform.SetValue(0); texCoordRange.SetValue(0.f, 0.f, 1.f, 1.f); colorUniform.SetValue(1.f, 1.f, 1.f, 1.f); qr.SetCoordAttributeIndex(positionAttribute()); device->BindFramebuffer(IGLDevice::Framebuffer, lastFb); device->BindTexture(IGLDevice::Texture2D, buf.GetTexture()); device->Viewport(0, 0, sW, sH); qr.Draw(); device->BindTexture(IGLDevice::Texture2D, 0); } else { device->Viewport(0, 0, sW, sH); device->BindFramebuffer(IGLDevice::Framebuffer, lastFb); } buf.Release(); }
GLColorBuffer GLDepthOfFieldFilter::Filter(GLColorBuffer input, float blurDepthRange, float vignetteBlur, float globalBlur) { SPADES_MARK_FUNCTION(); IGLDevice *dev = renderer->GetGLDevice(); GLQuadRenderer qr(dev); int w = dev->ScreenWidth(); int h = dev->ScreenHeight(); dev->Enable(IGLDevice::Blend, false); GLColorBuffer coc; globalBlur = std::min(globalBlur * 3.f, 1.f); { GLProfiler p(dev, "CoC Computation"); coc = GenerateCoC(blurDepthRange, vignetteBlur, globalBlur); } float maxCoc = (float)std::max(w, h) / 100.f; float cos60 = cosf(static_cast<float>(M_PI) / 3.f); float sin60 = sinf(static_cast<float>(M_PI) / 3.f); maxCoc *= .7f + vignetteBlur * 0.5f; maxCoc *= 1.f + 3.f * globalBlur; // reduce resolution to make it faster int divide = 1; int siz = std::max(w, h); GLColorBuffer lowbuf = input; while(siz >= 768) { divide <<= 1; siz >>= 1; lowbuf = UnderSample(lowbuf); } maxCoc /= (float)divide; dev->Viewport(0, 0, w / divide, h / divide); GLColorBuffer buf1, buf2; { GLProfiler p(dev, "Blur 1"); buf1 = Blur(lowbuf, coc, MakeVector2(0.f, -1.f) * maxCoc); } { GLProfiler p(dev, "Blur 2"); buf2 = Blur(lowbuf, coc, MakeVector2(-sin60, cos60) * maxCoc); lowbuf.Release(); } { GLProfiler p(dev, "Mix 1"); buf2 = AddMix(buf1, buf2); } //return buf2; { GLProfiler p(dev, "Blur 3"); buf1 = Blur(buf1, coc, MakeVector2(-sin60, cos60) * maxCoc); } { GLProfiler p(dev, "Blur 4"); buf2 = Blur(buf2, coc, MakeVector2(sin60, cos60) * maxCoc); } dev->Viewport(0, 0, w, h); { GLProfiler p(dev, "Mix 2"); GLColorBuffer output = FinalMix(input, buf1, buf2, coc); return output; } }