Add frame capture function to Renderer
parent
ec7b1acec9
commit
852874b32f
|
@ -638,24 +638,30 @@ CommandCapture::CommandCapture(std::string _type,
|
|||
{
|
||||
}
|
||||
|
||||
void CommandCapture::process(ExecutionEnvironment& /*unused*/)
|
||||
void CommandCapture::process(ExecutionEnvironment& env)
|
||||
{
|
||||
#ifndef TARGET_OS_MAC
|
||||
const Renderer* r = env.getRenderer();
|
||||
if (r == nullptr)
|
||||
return;
|
||||
|
||||
// Get the dimensions of the current viewport
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
array<int, 4> viewport;
|
||||
r->getScreenSize(viewport);
|
||||
|
||||
if (compareIgnoringCase(type, "jpeg") == 0)
|
||||
{
|
||||
CaptureGLBufferToJPEG(filename,
|
||||
viewport[0], viewport[1],
|
||||
viewport[2], viewport[3]);
|
||||
viewport[2], viewport[3],
|
||||
r);
|
||||
}
|
||||
else if (compareIgnoringCase(type, "png") == 0)
|
||||
{
|
||||
CaptureGLBufferToPNG(filename,
|
||||
viewport[0], viewport[1],
|
||||
viewport[2], viewport[3]);
|
||||
viewport[2], viewport[3],
|
||||
r);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -7879,3 +7879,36 @@ void Renderer::setSolarSystemMaxDistance(float t)
|
|||
if (t >= 1.0f && t <= 10.0f)
|
||||
SolarSystemMaxDistance = t;
|
||||
}
|
||||
|
||||
void Renderer::getScreenSize(int* x, int* y, int* w, int* h) const
|
||||
{
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
if (x != nullptr)
|
||||
*x = viewport[0];
|
||||
if (y != nullptr)
|
||||
*y = viewport[1];
|
||||
if (w != nullptr)
|
||||
*w = viewport[2];
|
||||
if (h != nullptr)
|
||||
*h = viewport[3];
|
||||
}
|
||||
|
||||
void Renderer::getScreenSize(std::array<int, 4>& viewport) const
|
||||
{
|
||||
static_assert(sizeof(int) == sizeof(GLint), "int and GLint size mismatch");
|
||||
glGetIntegerv(GL_VIEWPORT, &viewport[0]);
|
||||
}
|
||||
|
||||
constexpr GLenum toGLFormat(Renderer::PixelFormat format)
|
||||
{
|
||||
return (GLenum) format;
|
||||
}
|
||||
|
||||
bool Renderer::captureFrame(int x, int y, int w, int h, Renderer::PixelFormat format, unsigned char* buffer, bool back) const
|
||||
{
|
||||
glReadBuffer(back ? GL_BACK : GL_FRONT);
|
||||
glReadPixels(x, y, w, h, toGLFormat(format), GL_UNSIGNED_BYTE, (void*) buffer);
|
||||
|
||||
return glGetError == GL_NO_ERROR;
|
||||
}
|
||||
|
|
|
@ -195,6 +195,14 @@ class Renderer
|
|||
StarStyleCount = 3,
|
||||
};
|
||||
|
||||
// Pixel formats for image and video capture.
|
||||
// Currently we map them 1:1 to GL
|
||||
enum class PixelFormat
|
||||
{
|
||||
RGB = GL_RGB,
|
||||
BGR_EXT = GL_BGR_EXT
|
||||
};
|
||||
|
||||
// constants
|
||||
constexpr static const uint64_t DefaultRenderFlags =
|
||||
Renderer::ShowStars |
|
||||
|
@ -237,12 +245,16 @@ class Renderer
|
|||
void setOrbitMask(int);
|
||||
int getScreenDpi() const;
|
||||
void setScreenDpi(int);
|
||||
void getScreenSize(int* x, int* y, int* w, int* h) const;
|
||||
void getScreenSize(std::array<int, 4>& viewport) const;
|
||||
const ColorTemperatureTable* getStarColorTable() const;
|
||||
void setStarColorTable(const ColorTemperatureTable*);
|
||||
bool getVideoSync() const;
|
||||
void setVideoSync(bool);
|
||||
void setSolarSystemMaxDistance(float);
|
||||
|
||||
bool captureFrame(int, int, int, int, PixelFormat format, unsigned char*, bool = false) const;
|
||||
|
||||
#ifdef USE_HDR
|
||||
bool getBloomEnabled();
|
||||
void setBloomEnabled(bool);
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
using namespace std;
|
||||
|
||||
|
||||
AVICapture::AVICapture()
|
||||
AVICapture::AVICapture(const Renderer *r) :
|
||||
MovieCapture(r)
|
||||
{
|
||||
AVIFileInit();
|
||||
}
|
||||
|
@ -143,13 +144,13 @@ bool AVICapture::captureFrame()
|
|||
return false;
|
||||
|
||||
// Get the dimensions of the current viewport
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
int x, y, w, h;
|
||||
renderer->getScreenSize(&x, &y, &w, &h);
|
||||
|
||||
int x = viewport[0] + (viewport[2] - width) / 2;
|
||||
int y = viewport[1] + (viewport[3] - height) / 2;
|
||||
glReadPixels(x, y, width, height,
|
||||
GL_BGR_EXT, GL_UNSIGNED_BYTE,
|
||||
x += (w - width) / 2;
|
||||
y += (h - height) / 2;
|
||||
renderer->captureFrame(x, y, width, height,
|
||||
Renderer::PixelFormat::BGR_EXT,
|
||||
image);
|
||||
|
||||
int rowBytes = (width * 3 + 3) & ~0x3;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
class AVICapture : public MovieCapture
|
||||
{
|
||||
public:
|
||||
AVICapture();
|
||||
AVICapture(const Renderer *);
|
||||
virtual ~AVICapture();
|
||||
|
||||
bool start(const std::string& filename, int w, int h, float fps);
|
||||
|
|
|
@ -279,10 +279,11 @@ int celestia_getscreendimension(lua_State* l)
|
|||
// error checking only:
|
||||
this_celestia(l);
|
||||
// Get the dimensions of the current viewport
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
lua_pushnumber(l, viewport[2]);
|
||||
lua_pushnumber(l, viewport[3]);
|
||||
int w, h;
|
||||
CelestiaCore* appCore = to_celestia(l, 1);
|
||||
appCore->getRenderer()->getScreenSize(nullptr, nullptr, &w, &h);
|
||||
lua_pushnumber(l, w);
|
||||
lua_pushnumber(l, h);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -1920,8 +1921,8 @@ static int celestia_takescreenshot(lua_State* l)
|
|||
filenamestem = fmt::sprintf("screenshot-%s%06i", fileid, luastate->screenshotCount);
|
||||
|
||||
// Get the dimensions of the current viewport
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
array<GLint, 4> viewport;
|
||||
appCore->getRenderer()->getScreenSize(viewport);
|
||||
|
||||
#ifndef TARGET_OS_MAC
|
||||
if (strncmp(filetype, "jpg", 3) == 0)
|
||||
|
@ -1929,14 +1930,16 @@ static int celestia_takescreenshot(lua_State* l)
|
|||
string filepath = path + filenamestem + ".jpg";
|
||||
success = CaptureGLBufferToJPEG(filepath,
|
||||
viewport[0], viewport[1],
|
||||
viewport[2], viewport[3]);
|
||||
viewport[2], viewport[3],
|
||||
appCore->getRenderer());
|
||||
}
|
||||
else
|
||||
{
|
||||
string filepath = path + filenamestem + ".png";
|
||||
success = CaptureGLBufferToPNG(filepath,
|
||||
viewport[0], viewport[1],
|
||||
viewport[2], viewport[3]);
|
||||
viewport[2], viewport[3],
|
||||
appCore->getRenderer());
|
||||
}
|
||||
#endif
|
||||
lua_pushboolean(l, success);
|
||||
|
|
|
@ -1118,8 +1118,8 @@ static void openScript(const char* filename, AppData* app)
|
|||
static void captureImage(const char* filename, AppData* app)
|
||||
{
|
||||
/* Get the dimensions of the current viewport */
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
array<int, 4> viewport;
|
||||
app->renderer->getScreenSize(viewport);
|
||||
|
||||
bool success = false;
|
||||
ContentType type = DetermineFileType(filename);
|
||||
|
@ -1138,13 +1138,15 @@ static void captureImage(const char* filename, AppData* app)
|
|||
{
|
||||
success = CaptureGLBufferToJPEG(filename,
|
||||
viewport[0], viewport[1],
|
||||
viewport[2], viewport[3]);
|
||||
viewport[2], viewport[3],
|
||||
app->renderer);
|
||||
}
|
||||
else if (type == Content_PNG)
|
||||
{
|
||||
success = CaptureGLBufferToPNG(filename,
|
||||
viewport[0], viewport[1],
|
||||
viewport[2], viewport[3]);
|
||||
viewport[2], viewport[3],
|
||||
app->renderer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1175,10 +1177,10 @@ static void captureImage(const char* filename, AppData* app)
|
|||
static void captureMovie(const char* filename, int aspect, float fps, float quality, AppData* app)
|
||||
{
|
||||
/* Get the dimensions of the current viewport */
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
array<int, 4> viewport;
|
||||
app->renderer->getScreenSize(viewport);
|
||||
|
||||
MovieCapture* movieCapture = new OggTheoraCapture();
|
||||
MovieCapture* movieCapture = new OggTheoraCapture(app->renderer);
|
||||
switch (aspect)
|
||||
{
|
||||
case 0:
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
// of the License, or (at your option) any later version.
|
||||
|
||||
#include <celutil/debug.h>
|
||||
#include <GL/glew.h>
|
||||
#include <celengine/celestia.h>
|
||||
#include "imagecapture.h"
|
||||
|
||||
|
@ -23,18 +22,19 @@ using namespace std;
|
|||
|
||||
bool CaptureGLBufferToJPEG(const string& filename,
|
||||
int x, int y,
|
||||
int width, int height)
|
||||
int width, int height,
|
||||
const Renderer *renderer)
|
||||
{
|
||||
int rowStride = (width * 3 + 3) & ~0x3;
|
||||
int imageSize = height * rowStride;
|
||||
auto* pixels = new unsigned char[imageSize];
|
||||
|
||||
glReadBuffer(GL_BACK);
|
||||
glReadPixels(x, y, width, height,
|
||||
GL_RGB, GL_UNSIGNED_BYTE,
|
||||
pixels);
|
||||
|
||||
// TODO: Check for GL errors
|
||||
if (!renderer->captureFrame(x, y, width, height,
|
||||
Renderer::PixelFormat::RGB,
|
||||
pixels, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* out;
|
||||
out = fopen(filename.c_str(), "wb");
|
||||
|
@ -91,18 +91,19 @@ void PNGWriteData(png_structp png_ptr, png_bytep data, png_size_t length)
|
|||
|
||||
bool CaptureGLBufferToPNG(const string& filename,
|
||||
int x, int y,
|
||||
int width, int height)
|
||||
int width, int height,
|
||||
const Renderer *renderer)
|
||||
{
|
||||
int rowStride = (width * 3 + 3) & ~0x3;
|
||||
int imageSize = height * rowStride;
|
||||
auto* pixels = new unsigned char[imageSize];
|
||||
|
||||
glReadBuffer(GL_BACK);
|
||||
glReadPixels(x, y, width, height,
|
||||
GL_RGB, GL_UNSIGNED_BYTE,
|
||||
pixels);
|
||||
|
||||
// TODO: Check for GL errors
|
||||
if (!renderer->captureFrame(x, y, width, height,
|
||||
Renderer::PixelFormat::RGB,
|
||||
pixels, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* out;
|
||||
out = fopen(filename.c_str(), "wb");
|
||||
|
|
|
@ -11,13 +11,16 @@
|
|||
#define _IMAGECAPTURE_H_
|
||||
|
||||
#include <string>
|
||||
#include <celengine/render.h>
|
||||
|
||||
|
||||
extern bool CaptureGLBufferToJPEG(const std::string& filename,
|
||||
int x, int y,
|
||||
int width, int height);
|
||||
int width, int height,
|
||||
const Renderer *renderer);
|
||||
extern bool CaptureGLBufferToPNG(const std::string& filename,
|
||||
int x, int y,
|
||||
int width, int height);
|
||||
int width, int height,
|
||||
const Renderer *renderer);
|
||||
|
||||
#endif // _IMAGECAPTURE_H_
|
||||
|
|
|
@ -11,12 +11,13 @@
|
|||
#define _MOVIECAPTURE_H_
|
||||
|
||||
#include <string>
|
||||
#include <celengine/render.h>
|
||||
|
||||
|
||||
class MovieCapture
|
||||
{
|
||||
public:
|
||||
MovieCapture() {};
|
||||
MovieCapture(const Renderer *r) : renderer(r) {};
|
||||
virtual ~MovieCapture() {};
|
||||
|
||||
virtual bool start(const std::string& filename,
|
||||
|
@ -33,6 +34,9 @@ class MovieCapture
|
|||
virtual void setAspectRatio(int aspectNumerator, int aspectDenominator) = 0;
|
||||
virtual void setQuality(float) = 0;
|
||||
virtual void recordingStatus(bool started) = 0; /* to update UI recording status indicator */
|
||||
|
||||
protected:
|
||||
const Renderer *renderer{ nullptr };
|
||||
};
|
||||
|
||||
#endif // _MOVIECAPTURE_H_
|
||||
|
|
|
@ -84,7 +84,8 @@ using namespace std;
|
|||
// {"framerate-denominator",optional_argument,nullptr,'F'},
|
||||
|
||||
|
||||
OggTheoraCapture::OggTheoraCapture():
|
||||
OggTheoraCapture::OggTheoraCapture(const Renderer *r):
|
||||
MovieCapture(r),
|
||||
video_x(0),
|
||||
video_y(0),
|
||||
frame_x(0),
|
||||
|
@ -335,14 +336,14 @@ bool OggTheoraCapture::captureFrame()
|
|||
if(ogg_stream_eos(&to)) return false;
|
||||
|
||||
// Get the dimensions of the current viewport
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
int x, y, w, h;
|
||||
renderer->getScreenSize(&x, &y, &w, &h);
|
||||
|
||||
int x = viewport[0] + (viewport[2] - frame_x) / 2;
|
||||
int y = viewport[1] + (viewport[3] - frame_y) / 2;
|
||||
glReadPixels(x, y, frame_x, frame_y,
|
||||
GL_RGB, GL_UNSIGNED_BYTE,
|
||||
pixels);
|
||||
x += (w - frame_x) / 2;
|
||||
y += (h - frame_y) / 2;
|
||||
renderer->captureFrame(x, y, frame_x, frame_y,
|
||||
Renderer::PixelFormat::RGB,
|
||||
pixels);
|
||||
|
||||
unsigned char *ybase = yuvframe[0];
|
||||
unsigned char *ubase = yuvframe[0]+ video_x*video_y;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
class OggTheoraCapture : public MovieCapture
|
||||
{
|
||||
public:
|
||||
OggTheoraCapture();
|
||||
OggTheoraCapture(const Renderer*);
|
||||
virtual ~OggTheoraCapture();
|
||||
|
||||
bool start(const std::string& filename, int w, int h, float fps);
|
||||
|
|
|
@ -767,9 +767,9 @@ void CelestiaAppWindow::slotCaptureVideo()
|
|||
float frameRate = frameRateCombo->itemData(frameRateCombo->currentIndex()).toFloat();
|
||||
|
||||
#ifdef _WIN32
|
||||
MovieCapture* movieCapture = new AVICapture();
|
||||
MovieCapture* movieCapture = new AVICapture(m_appCore->getRenderer());
|
||||
#else
|
||||
MovieCapture* movieCapture = new OggTheoraCapture();
|
||||
MovieCapture* movieCapture = new OggTheoraCapture(m_appCore->getRenderer());
|
||||
movieCapture->setAspectRatio(1, 1);
|
||||
#endif
|
||||
bool ok = movieCapture->start(saveAsName.toLatin1().data(),
|
||||
|
|
|
@ -433,11 +433,12 @@ static void ShowLocalTime(CelestiaCore* appCore)
|
|||
}
|
||||
|
||||
|
||||
static bool BeginMovieCapture(const std::string& filename,
|
||||
static bool BeginMovieCapture(const Renderer* renderer,
|
||||
const std::string& filename,
|
||||
int width, int height,
|
||||
float framerate)
|
||||
{
|
||||
MovieCapture* movieCapture = new AVICapture();
|
||||
MovieCapture* movieCapture = new AVICapture(renderer);
|
||||
|
||||
bool success = movieCapture->start(filename, width, height, framerate);
|
||||
if (success)
|
||||
|
@ -2680,8 +2681,8 @@ static void HandleCaptureImage(HWND hWnd)
|
|||
// Ofn.lpstrFileTitle contains just the filename with extension
|
||||
|
||||
// Get the dimensions of the current viewport
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
array<int,4> viewport;
|
||||
appCore->getRenderer()->getScreenSize(viewport);
|
||||
|
||||
bool success = false;
|
||||
|
||||
|
@ -2727,13 +2728,15 @@ static void HandleCaptureImage(HWND hWnd)
|
|||
{
|
||||
success = CaptureGLBufferToJPEG(string(Ofn.lpstrFile),
|
||||
viewport[0], viewport[1],
|
||||
viewport[2], viewport[3]);
|
||||
viewport[2], viewport[3],
|
||||
appCore->getRenderer());
|
||||
}
|
||||
else if (nFileType == 2)
|
||||
{
|
||||
success = CaptureGLBufferToPNG(string(Ofn.lpstrFile),
|
||||
viewport[0], viewport[1],
|
||||
viewport[2], viewport[3]);
|
||||
viewport[2], viewport[3],
|
||||
appCore->getRenderer());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2846,7 +2849,8 @@ static void HandleCaptureMovie(HWND hWnd)
|
|||
}
|
||||
else
|
||||
{
|
||||
success = BeginMovieCapture(string(Ofn.lpstrFile),
|
||||
success = BeginMovieCapture(appCore->getRenderer(),
|
||||
string(Ofn.lpstrFile),
|
||||
MovieSizes[movieSize][0],
|
||||
MovieSizes[movieSize][1],
|
||||
MovieFramerates[movieFramerate]);
|
||||
|
|
Loading…
Reference in New Issue