2013-12-18 17:00:39 +09:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 yvt
|
|
|
|
|
|
|
|
This file is part of OpenSpades.
|
|
|
|
|
|
|
|
OpenSpades is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
OpenSpades 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 General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "SWRenderer.h"
|
|
|
|
#include "SWPort.h"
|
|
|
|
#include "Bitmap.h"
|
|
|
|
#include "SWImage.h"
|
|
|
|
#include "SWModel.h"
|
|
|
|
#include <Client/GameMap.h>
|
|
|
|
#include <stdlib.h>
|
2013-12-20 12:33:28 +09:00
|
|
|
#include "SWImageRenderer.h"
|
|
|
|
#include <array>
|
|
|
|
#include <algorithm>
|
2013-12-20 15:46:31 +09:00
|
|
|
#include <Core/Settings.h>
|
|
|
|
|
|
|
|
|
|
|
|
SPADES_SETTING(r_swStatistics, "0");
|
2013-12-18 17:00:39 +09:00
|
|
|
|
|
|
|
namespace spades {
|
|
|
|
namespace draw {
|
2013-12-20 12:33:28 +09:00
|
|
|
SWRenderer::SWRenderer(SWPort *port,
|
|
|
|
SWFeatureLevel level):
|
2013-12-18 17:00:39 +09:00
|
|
|
port(port),
|
|
|
|
map(nullptr),
|
|
|
|
fb(nullptr),
|
|
|
|
inited(false),
|
|
|
|
sceneUsedInThisFrame(false),
|
|
|
|
fogDistance(128.f),
|
|
|
|
fogColor(MakeVector3(0.f, 0.f, 0.f)),
|
|
|
|
drawColorAlphaPremultiplied(MakeVector4(1,1,1,1)),
|
|
|
|
legacyColorPremultiply(false),
|
|
|
|
lastTime(0),
|
2013-12-20 12:33:28 +09:00
|
|
|
duringSceneRendering(false),
|
|
|
|
featureLevel(level){
|
2013-12-18 17:00:39 +09:00
|
|
|
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
if(port == nullptr) {
|
|
|
|
SPRaise("Port is null.");
|
|
|
|
}
|
|
|
|
|
|
|
|
SPLog("---- SWRenderer early initialization started ---");
|
|
|
|
|
2013-12-20 12:33:28 +09:00
|
|
|
SPLog("creating image manager");
|
2013-12-18 17:00:39 +09:00
|
|
|
imageManager = std::make_shared<SWImageManager>();
|
|
|
|
|
2013-12-20 12:33:28 +09:00
|
|
|
SPLog("creating image renderer");
|
|
|
|
imageRenderer = std::make_shared<SWImageRenderer>(featureLevel);
|
2013-12-20 15:46:31 +09:00
|
|
|
imageRenderer->ResetPixelStatistics();
|
|
|
|
renderStopwatch.Reset();
|
2013-12-20 12:33:28 +09:00
|
|
|
|
|
|
|
SPLog("setting framebuffer.");
|
|
|
|
SetFramebuffer(port->GetFramebuffer());
|
|
|
|
|
|
|
|
// alloc depth buffer
|
|
|
|
SPLog("initializing depth buffer.");
|
|
|
|
depthBuffer.reserve(fb->GetWidth() * fb->GetHeight());
|
|
|
|
imageRenderer->SetDepthBuffer(depthBuffer.data());
|
2013-12-18 17:00:39 +09:00
|
|
|
|
|
|
|
SPLog("---- SWRenderer early initialization done ---");
|
|
|
|
}
|
|
|
|
|
|
|
|
SWRenderer::~SWRenderer() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
Shutdown();
|
|
|
|
}
|
|
|
|
|
2013-12-20 12:33:28 +09:00
|
|
|
void SWRenderer::SetFramebuffer(spades::Bitmap *bmp) {
|
|
|
|
if(bmp == nullptr) {
|
|
|
|
SPRaise("Framebuffer is null.");
|
|
|
|
}
|
|
|
|
if(fb) {
|
|
|
|
SPAssert(bmp->GetWidth() == fb->GetWidth());
|
|
|
|
SPAssert(bmp->GetHeight() == fb->GetHeight());
|
|
|
|
}
|
|
|
|
fb = bmp;
|
|
|
|
imageRenderer->SetFramebuffer(bmp);
|
|
|
|
}
|
|
|
|
|
2013-12-18 17:00:39 +09:00
|
|
|
void SWRenderer::Init() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
SPLog("---- SWRenderer late initialization started ---");
|
|
|
|
modelManager = std::make_shared<SWModelManager>();
|
|
|
|
|
|
|
|
|
|
|
|
SPLog("---- SWRenderer late initialization done ---");
|
|
|
|
|
|
|
|
inited = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::Shutdown() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
imageManager.reset();
|
|
|
|
modelManager.reset();
|
|
|
|
if(this->map)
|
|
|
|
this->map->SetListener(this);
|
|
|
|
map = nullptr;
|
|
|
|
port = nullptr;
|
|
|
|
|
|
|
|
inited = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
client::IImage *SWRenderer::RegisterImage(const char *filename) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureValid();
|
|
|
|
return imageManager->RegisterImage(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
client::IModel *SWRenderer::RegisterModel(const char *filename) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureInitialized();
|
|
|
|
return modelManager->RegisterModel(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
client::IImage *SWRenderer::CreateImage(spades::Bitmap *bmp) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureValid();
|
|
|
|
return imageManager->CreateImage(bmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
client::IModel *SWRenderer::CreateModel(spades::VoxelModel *model) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureInitialized();
|
|
|
|
return modelManager->CreateModel(model);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::SetGameMap(client::GameMap *map) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureInitialized();
|
|
|
|
if(this->map)
|
|
|
|
this->map->SetListener(nullptr);
|
|
|
|
this->map = map;
|
|
|
|
if(this->map)
|
|
|
|
this->map->SetListener(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::SetFogColor(spades::Vector3 v) {
|
|
|
|
fogColor = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SWRenderer::BuildProjectionMatrix() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
float near = sceneDef.zNear;
|
|
|
|
float far = sceneDef.zFar;
|
|
|
|
float t = near * tanf(sceneDef.fovY * .5f);
|
|
|
|
float r = near * tanf(sceneDef.fovX * .5f);
|
|
|
|
float a = r * 2.f, b = t * 2.f, c = far - near;
|
|
|
|
Matrix4 mat;
|
|
|
|
mat.m[0] = near * 2.f / a;
|
|
|
|
mat.m[1] = 0.f;
|
|
|
|
mat.m[2] = 0.f;
|
|
|
|
mat.m[3] = 0.f;
|
|
|
|
mat.m[4] = 0.f;
|
|
|
|
mat.m[5] = near * 2.f / b;
|
|
|
|
mat.m[6] = 0.f;
|
|
|
|
mat.m[7] = 0.f;
|
|
|
|
mat.m[8] = 0.f;
|
|
|
|
mat.m[9] = 0.f;
|
|
|
|
mat.m[10] = -(far + near) / c;
|
|
|
|
mat.m[11] = -1.f;
|
|
|
|
mat.m[12] = 0.f;
|
|
|
|
mat.m[13] = 0.f;
|
|
|
|
mat.m[14] = -(far * near * 2.f) / c;
|
|
|
|
mat.m[15] = 0.f;
|
|
|
|
projectionMatrix = mat;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::BuildView() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
Matrix4 mat = Matrix4::Identity();
|
|
|
|
mat.m[0] = sceneDef.viewAxis[0].x;
|
|
|
|
mat.m[4] = sceneDef.viewAxis[0].y;
|
|
|
|
mat.m[8] = sceneDef.viewAxis[0].z;
|
|
|
|
mat.m[1] = sceneDef.viewAxis[1].x;
|
|
|
|
mat.m[5] = sceneDef.viewAxis[1].y;
|
|
|
|
mat.m[9] = sceneDef.viewAxis[1].z;
|
|
|
|
mat.m[2] = -sceneDef.viewAxis[2].x;
|
|
|
|
mat.m[6] = -sceneDef.viewAxis[2].y;
|
|
|
|
mat.m[10] = -sceneDef.viewAxis[2].z;
|
|
|
|
|
|
|
|
Vector4 v = mat * sceneDef.viewOrigin;
|
|
|
|
mat.m[12] = -v.x;
|
|
|
|
mat.m[13] = -v.y;
|
|
|
|
mat.m[14] = -v.z;
|
|
|
|
|
|
|
|
viewMatrix = mat;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::BuildFrustrum() {
|
|
|
|
// far/near
|
|
|
|
frustrum[0] = Plane3::PlaneWithPointOnPlane(sceneDef.viewOrigin,
|
|
|
|
sceneDef.viewAxis[2]);
|
|
|
|
frustrum[1] = frustrum[0].Flipped();
|
|
|
|
frustrum[0].w -= sceneDef.zNear;
|
|
|
|
frustrum[1].w += sceneDef.zFar;
|
|
|
|
|
|
|
|
float xCos = cosf(sceneDef.fovX * .5f);
|
|
|
|
float xSin = sinf(sceneDef.fovX * .5f);
|
|
|
|
float yCos = cosf(sceneDef.fovY * .5f);
|
|
|
|
float ySin = sinf(sceneDef.fovY * .5f);
|
|
|
|
|
|
|
|
frustrum[2] = Plane3::PlaneWithPointOnPlane
|
|
|
|
(sceneDef.viewOrigin,
|
|
|
|
sceneDef.viewAxis[2] * xSin - sceneDef.viewAxis[0] * xCos);
|
|
|
|
frustrum[3] = Plane3::PlaneWithPointOnPlane
|
|
|
|
(sceneDef.viewOrigin,
|
|
|
|
sceneDef.viewAxis[2] * xSin + sceneDef.viewAxis[0] * xCos);
|
|
|
|
frustrum[4] = Plane3::PlaneWithPointOnPlane
|
|
|
|
(sceneDef.viewOrigin,
|
|
|
|
sceneDef.viewAxis[2] * ySin - sceneDef.viewAxis[1] * yCos);
|
|
|
|
frustrum[5] = Plane3::PlaneWithPointOnPlane
|
|
|
|
(sceneDef.viewOrigin,
|
|
|
|
sceneDef.viewAxis[2] * ySin + sceneDef.viewAxis[1] * yCos);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::EnsureSceneStarted() {
|
|
|
|
SPADES_MARK_FUNCTION_DEBUG();
|
|
|
|
if(!duringSceneRendering) {
|
|
|
|
SPRaise("Illegal call outside of StartScene ... EndScene");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::EnsureSceneNotStarted() {
|
|
|
|
SPADES_MARK_FUNCTION_DEBUG();
|
|
|
|
if(duringSceneRendering) {
|
|
|
|
SPRaise("Illegal call between StartScene ... EndScene");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::EnsureInitialized() {
|
|
|
|
SPADES_MARK_FUNCTION_DEBUG();
|
|
|
|
if(!inited){
|
|
|
|
SPRaise("Renderer is not initialized");
|
|
|
|
}
|
|
|
|
EnsureValid();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::EnsureValid() {
|
|
|
|
SPADES_MARK_FUNCTION_DEBUG();
|
|
|
|
if(!port){
|
|
|
|
SPRaise("Renderer is not valid");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::StartScene(const client::SceneDefinition &def) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
EnsureInitialized();
|
|
|
|
EnsureSceneNotStarted();
|
|
|
|
|
|
|
|
sceneDef = def;
|
|
|
|
duringSceneRendering = true;
|
|
|
|
|
|
|
|
BuildProjectionMatrix();
|
|
|
|
BuildView();
|
|
|
|
BuildFrustrum();
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::RenderModel(client::IModel *model, const client::ModelRenderParam &) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureInitialized();
|
|
|
|
EnsureSceneStarted();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::AddLight(const client::DynamicLightParam &light) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureInitialized();
|
|
|
|
EnsureSceneStarted();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::AddDebugLine(spades::Vector3 a, spades::Vector3 b, spades::Vector4 color) {
|
|
|
|
EnsureInitialized();
|
|
|
|
EnsureSceneStarted();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::AddSprite(client::IImage *, spades::Vector3 center, float radius, float rotation) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureInitialized();
|
|
|
|
EnsureSceneStarted();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::AddLongSprite(client::IImage *, spades::Vector3 p1, spades::Vector3 p2, float radius) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureInitialized();
|
|
|
|
EnsureSceneStarted();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-12-20 12:33:28 +09:00
|
|
|
static uint32_t ConvertColor32(Vector4 col) {
|
|
|
|
auto convertColor = [](float f) {
|
|
|
|
int i = static_cast<int>(f * 255.f + .5f);
|
|
|
|
return static_cast<uint32_t>(std::max(std::min(i, 255), 0));
|
|
|
|
};
|
|
|
|
uint32_t c;
|
|
|
|
c = convertColor(col.x);
|
|
|
|
c |= convertColor(col.y) << 8;
|
|
|
|
c |= convertColor(col.z) << 16;
|
|
|
|
c |= convertColor(col.w) << 24;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2013-12-18 17:00:39 +09:00
|
|
|
void SWRenderer::EndScene() {
|
|
|
|
EnsureInitialized();
|
|
|
|
EnsureSceneStarted();
|
|
|
|
|
2013-12-20 12:33:28 +09:00
|
|
|
// clear scene
|
|
|
|
std::fill(fb->GetPixels(), fb->GetPixels() +
|
|
|
|
fb->GetWidth() * fb->GetHeight(),
|
|
|
|
ConvertColor32(MakeVector4(fogColor.x, fogColor.y, fogColor.z, 1.f)));
|
|
|
|
std::fill(fb->GetPixels(), fb->GetPixels() +
|
|
|
|
fb->GetWidth() * fb->GetHeight(),
|
|
|
|
0x7f7f7f);
|
|
|
|
|
|
|
|
|
2013-12-18 17:00:39 +09:00
|
|
|
duringSceneRendering = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::MultiplyScreenColor(spades::Vector3 v) {
|
|
|
|
EnsureSceneNotStarted();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::SetColor(spades::Vector4 col) {
|
|
|
|
EnsureValid();
|
|
|
|
drawColorAlphaPremultiplied = col;
|
|
|
|
legacyColorPremultiply = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::SetColorAlphaPremultiplied(spades::Vector4 col) {
|
|
|
|
EnsureValid();
|
|
|
|
legacyColorPremultiply = false;
|
|
|
|
drawColorAlphaPremultiplied = col;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SWRenderer::DrawImage(client::IImage *image,
|
|
|
|
const spades::Vector2 &outTopLeft) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
DrawImage(image,
|
|
|
|
AABB2(outTopLeft.x, outTopLeft.y,
|
|
|
|
image->GetWidth(),
|
|
|
|
image->GetHeight()),
|
|
|
|
AABB2(0, 0,
|
|
|
|
image->GetWidth(),
|
|
|
|
image->GetHeight()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::DrawImage(client::IImage *image, const spades::AABB2 &outRect) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
DrawImage(image,
|
|
|
|
outRect,
|
|
|
|
AABB2(0, 0,
|
|
|
|
image->GetWidth(),
|
|
|
|
image->GetHeight()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::DrawImage(client::IImage *image,
|
|
|
|
const spades::Vector2 &outTopLeft,
|
|
|
|
const spades::AABB2 &inRect) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
DrawImage(image,
|
|
|
|
AABB2(outTopLeft.x, outTopLeft.y,
|
|
|
|
inRect.GetWidth(),
|
|
|
|
inRect.GetHeight()),
|
|
|
|
inRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::DrawImage(client::IImage *image,
|
|
|
|
const spades::AABB2 &outRect,
|
|
|
|
const spades::AABB2 &inRect) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
DrawImage(image,
|
|
|
|
Vector2::Make(outRect.GetMinX(), outRect.GetMinY()),
|
|
|
|
Vector2::Make(outRect.GetMaxX(), outRect.GetMinY()),
|
|
|
|
Vector2::Make(outRect.GetMinX(), outRect.GetMaxY()),
|
|
|
|
inRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::DrawImage(client::IImage *image,
|
|
|
|
const spades::Vector2 &outTopLeft,
|
|
|
|
const spades::Vector2 &outTopRight,
|
|
|
|
const spades::Vector2 &outBottomLeft,
|
|
|
|
const spades::AABB2 &inRect) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
EnsureValid();
|
|
|
|
EnsureSceneNotStarted();
|
|
|
|
|
|
|
|
// d = a + (b - a) + (c - a)
|
|
|
|
// = b + c - a
|
|
|
|
Vector2 outBottomRight = outTopRight + outBottomLeft - outTopLeft;
|
2013-12-20 12:33:28 +09:00
|
|
|
|
|
|
|
SWImage *img = dynamic_cast<SWImage *>(image);
|
2013-12-18 17:00:39 +09:00
|
|
|
if(!img){
|
|
|
|
SPInvalidArgument("image");
|
|
|
|
}
|
|
|
|
|
2013-12-20 12:33:28 +09:00
|
|
|
imageRenderer->SetShaderType(SWImageRenderer::ShaderType::Image);
|
2013-12-18 17:00:39 +09:00
|
|
|
|
|
|
|
Vector4 col = drawColorAlphaPremultiplied;
|
|
|
|
if(legacyColorPremultiply) {
|
|
|
|
// in legacy mode, image color is
|
|
|
|
// non alpha-premultiplied.
|
|
|
|
col.x *= col.w;
|
|
|
|
col.y *= col.w;
|
|
|
|
col.z *= col.w;
|
|
|
|
}
|
|
|
|
|
2013-12-20 12:33:28 +09:00
|
|
|
std::array<SWImageRenderer::Vertex, 4> vtx;
|
|
|
|
vtx[0].color = col;
|
|
|
|
vtx[1].color = col;
|
|
|
|
vtx[2].color = col;
|
|
|
|
vtx[3].color = col;
|
|
|
|
|
|
|
|
vtx[0].position = MakeVector4(outTopLeft.x, outTopLeft.y,
|
|
|
|
1.f, 1.f);
|
|
|
|
vtx[1].position = MakeVector4(outTopRight.x, outTopRight.y,
|
|
|
|
1.f, 1.f);
|
|
|
|
vtx[2].position = MakeVector4(outBottomLeft.x, outBottomLeft.y,
|
|
|
|
1.f, 1.f);
|
|
|
|
vtx[3].position = MakeVector4(outBottomRight.x, outBottomRight.y,
|
|
|
|
1.f, 1.f);
|
|
|
|
Vector2 scl = {img->GetInvWidth(), img->GetInvHeight()};
|
|
|
|
vtx[0].uv = MakeVector2(inRect.min.x, inRect.min.y) * scl;
|
|
|
|
vtx[1].uv = MakeVector2(inRect.max.x, inRect.min.y) * scl;
|
|
|
|
vtx[2].uv = MakeVector2(inRect.min.x, inRect.max.y) * scl;
|
|
|
|
vtx[3].uv = MakeVector2(inRect.max.x, inRect.max.y) * scl;
|
|
|
|
|
|
|
|
imageRenderer->DrawPolygon(img, vtx[0], vtx[1], vtx[2]);
|
|
|
|
imageRenderer->DrawPolygon(img, vtx[1], vtx[3], vtx[2]);
|
2013-12-18 17:00:39 +09:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::DrawFlatGameMap(const spades::AABB2 &outRect, const spades::AABB2 &inRect) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureValid();
|
|
|
|
EnsureSceneNotStarted();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::FrameDone() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureValid();
|
|
|
|
EnsureSceneNotStarted();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::Flip() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureValid();
|
|
|
|
EnsureSceneNotStarted();
|
|
|
|
|
2013-12-20 15:46:31 +09:00
|
|
|
if(r_swStatistics) {
|
|
|
|
double dur = renderStopwatch.GetTime();
|
|
|
|
SPLog("==== SWRenderer Statistics ====");
|
|
|
|
SPLog("Elapsed Time: %.3fus", dur * 1000000.0);
|
|
|
|
SPLog("Polygon pixels drawn: %llu", imageRenderer->GetPixelsDrawn());
|
|
|
|
}
|
|
|
|
|
|
|
|
imageRenderer->ResetPixelStatistics();
|
|
|
|
renderStopwatch.Reset();
|
|
|
|
|
2013-12-18 17:00:39 +09:00
|
|
|
{
|
|
|
|
uint32_t rdb = rand();
|
|
|
|
uint32_t *ptr = fb->GetPixels();
|
2013-12-20 12:33:28 +09:00
|
|
|
for(int pixels = fb->GetWidth() * fb->GetHeight() / 10;
|
2013-12-18 17:00:39 +09:00
|
|
|
pixels > 0; pixels--) {
|
|
|
|
*ptr = ((rdb >> 16) & 0xff) * 0x10101;
|
|
|
|
rdb = (rdb * 34563511) ^ 1245525;
|
|
|
|
rdb += (pixels >> 10) + 1;
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
port->Swap();
|
|
|
|
|
|
|
|
// next frame's framebuffer
|
2013-12-20 12:33:28 +09:00
|
|
|
SetFramebuffer(port->GetFramebuffer());
|
2013-12-18 17:00:39 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
Bitmap *SWRenderer::ReadBitmap() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureValid();
|
|
|
|
EnsureSceneNotStarted();
|
|
|
|
return fb->Clone();
|
|
|
|
}
|
|
|
|
|
|
|
|
float SWRenderer::ScreenWidth() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureValid();
|
|
|
|
return static_cast<float>(fb->GetWidth());
|
|
|
|
}
|
|
|
|
|
|
|
|
float SWRenderer::ScreenHeight() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
EnsureValid();
|
|
|
|
return static_cast<float>(fb->GetHeight());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SWRenderer::BoxFrustrumCull(const AABB3& box) {
|
|
|
|
/*if(IsRenderingMirror()) {
|
|
|
|
// reflect
|
|
|
|
AABB3 bx = box;
|
|
|
|
std::swap(bx.min.z, bx.max.z);
|
|
|
|
bx.min.z = 63.f * 2.f - bx.min.z;
|
|
|
|
bx.max.z = 63.f * 2.f - bx.max.z;
|
|
|
|
return PlaneCullTest(frustrum[0], bx) &&
|
|
|
|
PlaneCullTest(frustrum[1], bx) &&
|
|
|
|
PlaneCullTest(frustrum[2], bx) &&
|
|
|
|
PlaneCullTest(frustrum[3], bx) &&
|
|
|
|
PlaneCullTest(frustrum[4], bx) &&
|
|
|
|
PlaneCullTest(frustrum[5], bx);
|
|
|
|
}*/
|
|
|
|
return PlaneCullTest(frustrum[0], box) &&
|
|
|
|
PlaneCullTest(frustrum[1], box) &&
|
|
|
|
PlaneCullTest(frustrum[2], box) &&
|
|
|
|
PlaneCullTest(frustrum[3], box) &&
|
|
|
|
PlaneCullTest(frustrum[4], box) &&
|
|
|
|
PlaneCullTest(frustrum[5], box);
|
|
|
|
}
|
|
|
|
bool SWRenderer::SphereFrustrumCull(const Vector3& center,
|
|
|
|
float radius) {
|
|
|
|
/*if(IsRenderingMirror()) {
|
|
|
|
// reflect
|
|
|
|
Vector3 vx = center;
|
|
|
|
vx.z = 63.f * 2.f - vx.z;
|
|
|
|
for(int i = 0; i < 6; i++){
|
|
|
|
if(frustrum[i].GetDistanceTo(vx) < -radius)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}*/
|
|
|
|
for(int i = 0; i < 6; i++){
|
|
|
|
if(frustrum[i].GetDistanceTo(center) < -radius)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SWRenderer::GameMapChanged(int x, int y, int z, client::GameMap *map) {
|
|
|
|
if(map != this->map) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|