Compare commits
4 Commits
temp-ui-cp
...
ge_2df_tex
Author | SHA1 | Date | |
---|---|---|---|
4ef064d4c2 | |||
9bf3c96376 | |||
9847537979 | |||
e4ea5e5810 |
@@ -641,7 +641,7 @@ int GPU_verify_image(
|
||||
}
|
||||
|
||||
/* TODO unneeded when float images are correctly treated as linear always */
|
||||
if (!is_data) {
|
||||
if (!is_data && !(ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) {
|
||||
do_color_management = true;
|
||||
}
|
||||
}
|
||||
|
@@ -122,6 +122,23 @@ static BlendFileData *load_game_data(const char *filename)
|
||||
return bfd;
|
||||
}
|
||||
|
||||
static void BL_KetsjiRender(KX_KetsjiEngine *ketsjiengine, ARegion *ar, Scene *scene, int draw_letterbox)
|
||||
{
|
||||
if (draw_letterbox) {
|
||||
// Clear screen to border color
|
||||
// We do this here since we set the canvas to be within the frames. This means the engine
|
||||
// itself is unaware of the extra space, so we clear the whole region for it.
|
||||
glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f);
|
||||
glViewport(ar->winrct.xmin, ar->winrct.ymin,
|
||||
BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
// render the frame
|
||||
ketsjiengine->Render();
|
||||
|
||||
}
|
||||
|
||||
static int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWindow *win, Scene *scene, ARegion *ar,
|
||||
KX_BlenderKeyboardDevice* keyboarddevice, KX_BlenderMouseDevice* mousedevice, int draw_letterbox)
|
||||
{
|
||||
@@ -134,18 +151,7 @@ static int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWind
|
||||
bool render = ketsjiengine->NextFrame();
|
||||
|
||||
if (render) {
|
||||
if (draw_letterbox) {
|
||||
// Clear screen to border color
|
||||
// We do this here since we set the canvas to be within the frames. This means the engine
|
||||
// itself is unaware of the extra space, so we clear the whole region for it.
|
||||
glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f);
|
||||
glViewport(ar->winrct.xmin, ar->winrct.ymin,
|
||||
BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
// render the frame
|
||||
ketsjiengine->Render();
|
||||
BL_KetsjiRender(ketsjiengine, ar, scene, draw_letterbox);
|
||||
}
|
||||
|
||||
wm_window_process_events_nosleep();
|
||||
@@ -211,6 +217,13 @@ static int BL_KetsjiPyNextFrame(void *state0)
|
||||
state->mousedevice,
|
||||
state->draw_letterbox);
|
||||
}
|
||||
|
||||
static void BL_KetsjiPyRender(void *state0)
|
||||
{
|
||||
BL_KetsjiNextFrameState *state = (BL_KetsjiNextFrameState *) state0;
|
||||
BL_KetsjiRender(state->ketsjiengine, state->ar, state->scene, state->draw_letterbox);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -526,6 +539,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
|
||||
char *python_main = NULL;
|
||||
pynextframestate.state = NULL;
|
||||
pynextframestate.func = NULL;
|
||||
pynextframestate.render = NULL;
|
||||
python_main = KX_GetPythonMain(scene);
|
||||
|
||||
// the mainloop
|
||||
@@ -548,6 +562,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
|
||||
|
||||
pynextframestate.state = &ketsjinextframestate;
|
||||
pynextframestate.func = &BL_KetsjiPyNextFrame;
|
||||
pynextframestate.render = &BL_KetsjiPyRender;
|
||||
printf("Yielding control to Python script '%s'...\n", python_main);
|
||||
PyRun_SimpleString(python_code);
|
||||
printf("Exit Python script '%s'\n", python_main);
|
||||
|
@@ -210,8 +210,8 @@ SetViewPort(
|
||||
* the width,height is calculated including both pixels
|
||||
* therefore: max - min + 1
|
||||
*/
|
||||
int vp_width = (x2 - x1) + 1;
|
||||
int vp_height = (y2 - y1) + 1;
|
||||
int vp_width = (x2 - x1);
|
||||
int vp_height = (y2 - y1);
|
||||
int minx = m_frame_rect.GetLeft();
|
||||
int miny = m_frame_rect.GetBottom();
|
||||
|
||||
|
@@ -69,6 +69,7 @@
|
||||
#include "KX_SCA_DynamicActuator.h"
|
||||
#include "KX_SteeringActuator.h"
|
||||
#include "KX_MouseActuator.h"
|
||||
#include "KX_BlenderMaterial.h"
|
||||
|
||||
#include "KX_Scene.h"
|
||||
#include "KX_KetsjiEngine.h"
|
||||
@@ -911,6 +912,7 @@ void BL_ConvertActuators(const char* maggiename,
|
||||
{
|
||||
bTwoDFilterActuator *_2dfilter = (bTwoDFilterActuator*) bact->data;
|
||||
SCA_2DFilterActuator *tmp = NULL;
|
||||
BL_Material *mat = NULL;
|
||||
|
||||
RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode;
|
||||
switch (_2dfilter->type) {
|
||||
@@ -949,6 +951,16 @@ void BL_ConvertActuators(const char* maggiename,
|
||||
break;
|
||||
case ACT_2DFILTER_CUSTOMFILTER:
|
||||
filtermode = RAS_2DFilterManager::RAS_2DFILTER_CUSTOMFILTER;
|
||||
if (gameobj->GetMeshCount() > 0) {
|
||||
unsigned int matid = 0;
|
||||
RAS_MeshMaterial *meshMat = gameobj->GetMesh(0)->GetMeshMaterial(matid);
|
||||
if (meshMat != NULL && meshMat->m_bucket != NULL) {
|
||||
RAS_IPolyMaterial *polymat = meshMat->m_bucket->GetPolyMaterial();
|
||||
if (polymat->GetFlag() & RAS_BLENDERGLSL) {
|
||||
mat = ((KX_BlenderMaterial *)polymat)->GetBLMaterial();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACT_2DFILTER_NOFILTER:
|
||||
filtermode = RAS_2DFilterManager::RAS_2DFILTER_NOFILTER;
|
||||
@@ -964,7 +976,7 @@ void BL_ConvertActuators(const char* maggiename,
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag,
|
||||
tmp = new SCA_2DFilterActuator(gameobj, mat, filtermode, _2dfilter->flag,
|
||||
_2dfilter->float_arg, _2dfilter->int_arg,
|
||||
ketsjiEngine->GetRasterizer(), scene);
|
||||
|
||||
|
@@ -40,6 +40,7 @@ SCA_2DFilterActuator::~SCA_2DFilterActuator()
|
||||
|
||||
SCA_2DFilterActuator::SCA_2DFilterActuator(
|
||||
SCA_IObject *gameobj,
|
||||
BL_Material *mat,
|
||||
RAS_2DFilterManager::RAS_2DFILTER_MODE type,
|
||||
short flag,
|
||||
float float_arg,
|
||||
@@ -55,9 +56,11 @@ SCA_2DFilterActuator::SCA_2DFilterActuator(
|
||||
m_scene(scene)
|
||||
{
|
||||
m_gameobj = NULL;
|
||||
m_mat = NULL;
|
||||
if (gameobj) {
|
||||
m_propNames = gameobj->GetPropertyNames();
|
||||
m_gameobj = gameobj;
|
||||
m_mat = mat;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +93,7 @@ bool SCA_2DFilterActuator::Update()
|
||||
}
|
||||
else if (m_type < RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS)
|
||||
{
|
||||
m_scene->Update2DFilter(m_propNames, m_gameobj, m_type, m_int_arg, m_shaderText);
|
||||
m_scene->Update2DFilter(m_propNames, m_gameobj, m_mat, m_type, m_int_arg, m_shaderText);
|
||||
}
|
||||
// once the filter is in place, no need to update it again => disable the actuator
|
||||
return false;
|
||||
|
@@ -35,6 +35,8 @@
|
||||
#include "SCA_IActuator.h"
|
||||
#include "SCA_IScene.h"
|
||||
|
||||
class BL_Material;
|
||||
|
||||
class SCA_2DFilterActuator : public SCA_IActuator
|
||||
{
|
||||
Py_Header
|
||||
@@ -48,11 +50,13 @@ private:
|
||||
STR_String m_shaderText;
|
||||
RAS_IRasterizer* m_rasterizer;
|
||||
SCA_IScene* m_scene;
|
||||
BL_Material* m_mat;
|
||||
|
||||
public:
|
||||
|
||||
SCA_2DFilterActuator(
|
||||
class SCA_IObject* gameobj,
|
||||
BL_Material *mat,
|
||||
RAS_2DFilterManager::RAS_2DFILTER_MODE type,
|
||||
short flag,
|
||||
float float_arg,
|
||||
|
@@ -74,7 +74,8 @@ public:
|
||||
void RemoveDebugProperty(class CValue *gameobj, const STR_String &name);
|
||||
void RemoveObjectDebugProperties(class CValue* gameobj);
|
||||
|
||||
virtual void Update2DFilter(std::vector<STR_String>& propNames, void* gameObj,
|
||||
virtual void Update2DFilter(std::vector<STR_String>& propNames, void* gameObj,
|
||||
void *mat,
|
||||
RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode,
|
||||
int pass, STR_String& text) {}
|
||||
|
||||
|
@@ -97,11 +97,11 @@ void GPC_Canvas::SetViewPort(int x1, int y1, int x2, int y2)
|
||||
|
||||
m_viewport[0] = x1;
|
||||
m_viewport[1] = y1;
|
||||
m_viewport[2] = x2-x1 + 1;
|
||||
m_viewport[3] = y2-y1 + 1;
|
||||
m_viewport[2] = x2-x1;
|
||||
m_viewport[3] = y2-y1;
|
||||
|
||||
glViewport(x1,y1,x2-x1 + 1,y2-y1 + 1);
|
||||
glScissor(x1,y1,x2-x1 + 1,y2-y1 + 1);
|
||||
glViewport(x1,y1,x2-x1,y2-y1);
|
||||
glScissor(x1,y1,x2-x1,y2-y1);
|
||||
}
|
||||
|
||||
void GPC_Canvas::UpdateViewPort(int x1, int y1, int x2, int y2)
|
||||
|
@@ -848,6 +848,12 @@ void GPG_Application::EngineNextFrame()
|
||||
m_exitString = m_ketsjiengine->GetExitString();
|
||||
}
|
||||
|
||||
void GPG_Application::EngineRender()
|
||||
{
|
||||
// render the frame
|
||||
m_ketsjiengine->Render();
|
||||
}
|
||||
|
||||
void GPG_Application::exitEngine()
|
||||
{
|
||||
// We only want to kill the engine if it has been initialized
|
||||
|
@@ -93,6 +93,7 @@ public:
|
||||
bool StartGameEngine(int stereoMode);
|
||||
void StopGameEngine();
|
||||
void EngineNextFrame();
|
||||
void EngineRender();
|
||||
|
||||
protected:
|
||||
bool handleWheel(GHOST_IEvent* event);
|
||||
|
@@ -385,6 +385,11 @@ static bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exit
|
||||
return run;
|
||||
}
|
||||
|
||||
static void GPG_Render(GPG_Application *app)
|
||||
{
|
||||
app->EngineRender();
|
||||
}
|
||||
|
||||
struct GPG_NextFrameState {
|
||||
GHOST_ISystem* system;
|
||||
GPG_Application *app;
|
||||
@@ -405,6 +410,12 @@ static int GPG_PyNextFrame(void *state0)
|
||||
}
|
||||
}
|
||||
|
||||
static void GPG_PyRender(void *state0)
|
||||
{
|
||||
GPG_NextFrameState *state = (GPG_NextFrameState *) state0;
|
||||
GPG_Render(state->app);
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
#ifdef WIN32
|
||||
@@ -562,6 +573,7 @@ int main(
|
||||
U.anisotropic_filter = 2;
|
||||
// enable fast mipmap generation
|
||||
U.use_gpu_mipmap = 1;
|
||||
U.use_16bit_textures = 1;
|
||||
|
||||
BKE_sound_init_once();
|
||||
|
||||
@@ -1123,6 +1135,7 @@ int main(
|
||||
char *python_main = NULL;
|
||||
pynextframestate.state = NULL;
|
||||
pynextframestate.func = NULL;
|
||||
pynextframestate.render = NULL;
|
||||
#ifdef WITH_PYTHON
|
||||
python_main = KX_GetPythonMain(scene);
|
||||
#endif // WITH_PYTHON
|
||||
@@ -1140,6 +1153,7 @@ int main(
|
||||
gpg_nextframestate.gs = &gs;
|
||||
pynextframestate.state = &gpg_nextframestate;
|
||||
pynextframestate.func = &GPG_PyNextFrame;
|
||||
pynextframestate.render = &GPG_PyRender;
|
||||
|
||||
printf("Yielding control to Python script '%s'...\n", python_main);
|
||||
PyRun_SimpleString(python_code);
|
||||
|
@@ -2018,7 +2018,7 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
|
||||
if (!cam)
|
||||
return;
|
||||
|
||||
m_canvas->SetViewPort(0,0,m_buffersize-1,m_buffersize-1);
|
||||
m_canvas->SetViewPort(0,0,m_buffersize,m_buffersize);
|
||||
|
||||
// m_rasterizer->SetAmbient();
|
||||
m_rasterizer->DisplayFog();
|
||||
|
@@ -52,6 +52,7 @@
|
||||
#include "RAS_IRasterizer.h"
|
||||
#include "RAS_ICanvas.h"
|
||||
#include "RAS_ILightObject.h"
|
||||
#include "RAS_IOffScreen.h"
|
||||
#include "MT_Vector3.h"
|
||||
#include "MT_Transform.h"
|
||||
#include "SCA_IInputDevice.h"
|
||||
@@ -109,6 +110,7 @@ double KX_KetsjiEngine::m_average_framerate = 0.0;
|
||||
bool KX_KetsjiEngine::m_restrict_anim_fps = false;
|
||||
short KX_KetsjiEngine::m_exitkey = 130; // ESC Key
|
||||
bool KX_KetsjiEngine::m_doRender = true;
|
||||
bool KX_KetsjiEngine::m_doOffScreen = false;
|
||||
|
||||
/**
|
||||
* Constructor of the Ketsji Engine
|
||||
@@ -116,6 +118,7 @@ bool KX_KetsjiEngine::m_doRender = true;
|
||||
KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
|
||||
: m_canvas(NULL),
|
||||
m_rasterizer(NULL),
|
||||
m_offScreenRender(NULL),
|
||||
m_kxsystem(system),
|
||||
m_sceneconverter(NULL),
|
||||
m_networkdevice(NULL),
|
||||
@@ -778,6 +781,16 @@ bool KX_KetsjiEngine::NextFrame()
|
||||
return doRender && m_doRender;
|
||||
}
|
||||
|
||||
void KX_KetsjiEngine::BindOffScreen(bool bind)
|
||||
{
|
||||
if (m_doOffScreen && m_offScreenRender)
|
||||
{
|
||||
if (bind)
|
||||
m_offScreenRender->Bind(RAS_IOffScreen::RAS_OFS_BIND_READ);
|
||||
else
|
||||
m_offScreenRender->Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KX_KetsjiEngine::Render()
|
||||
@@ -797,9 +810,12 @@ void KX_KetsjiEngine::Render()
|
||||
if (m_hideCursor)
|
||||
m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
|
||||
|
||||
m_canvas->BeginDraw();
|
||||
// redirect render if requested
|
||||
if (m_doOffScreen && m_offScreenRender)
|
||||
m_offScreenRender->Bind(RAS_IOffScreen::RAS_OFS_BIND_RENDER);
|
||||
// clear the entire game screen with the border color
|
||||
// only once per frame
|
||||
m_canvas->BeginDraw();
|
||||
if (m_rasterizer->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
|
||||
m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
|
||||
if (m_overrideFrameColor)
|
||||
@@ -845,7 +861,10 @@ void KX_KetsjiEngine::Render()
|
||||
//scene->UpdateMeshTransformations();
|
||||
|
||||
// shadow buffers
|
||||
RenderShadowBuffers(scene);
|
||||
if (RenderShadowBuffers(scene) && m_doOffScreen && m_offScreenRender)
|
||||
// shadow render restore the frame buffer, must restore it if we have a customer render buffer
|
||||
m_offScreenRender->Bind(RAS_IOffScreen::RAS_OFS_BIND_RENDER);
|
||||
|
||||
|
||||
// Avoid drawing the scene with the active camera twice when its viewport is enabled
|
||||
if (cam && !cam->GetViewport())
|
||||
@@ -929,6 +948,8 @@ void KX_KetsjiEngine::Render()
|
||||
PostRenderScene(scene);
|
||||
}
|
||||
} // if (m_rasterizer->Stereo())
|
||||
if (m_doOffScreen && m_offScreenRender)
|
||||
m_offScreenRender->Unbind();
|
||||
|
||||
EndFrame();
|
||||
}
|
||||
@@ -1085,10 +1106,11 @@ void KX_KetsjiEngine::UpdateAnimations(KX_Scene *scene)
|
||||
scene->UpdateAnimations(m_frameTime);
|
||||
}
|
||||
|
||||
void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
|
||||
bool KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
|
||||
{
|
||||
CListValue *lightlist = scene->GetLightList();
|
||||
int i, drawmode;
|
||||
bool hasShadow = false;
|
||||
|
||||
m_rasterizer->SetAuxilaryClientInfo(scene);
|
||||
|
||||
@@ -1135,10 +1157,12 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
|
||||
raslight->UnbindShadowBuffer();
|
||||
m_rasterizer->SetDrawingMode(drawmode);
|
||||
cam->Release();
|
||||
hasShadow = true;
|
||||
}
|
||||
}
|
||||
/* remember that we have a valid shadow buffer for that scene */
|
||||
scene->SetShadowDone(true);
|
||||
return hasShadow;
|
||||
}
|
||||
|
||||
// update graphics
|
||||
@@ -1335,6 +1359,11 @@ void KX_KetsjiEngine::StopEngine()
|
||||
}
|
||||
m_scenes.clear();
|
||||
|
||||
if (m_offScreenRender)
|
||||
{
|
||||
delete m_offScreenRender;
|
||||
m_offScreenRender = NULL;
|
||||
}
|
||||
// cleanup all the stuff
|
||||
m_rasterizer->Exit();
|
||||
}
|
||||
@@ -1941,6 +1970,17 @@ bool KX_KetsjiEngine::GetRender()
|
||||
return m_doRender;
|
||||
}
|
||||
|
||||
void KX_KetsjiEngine::SetOffScreen(bool offScreen)
|
||||
{
|
||||
m_doOffScreen = offScreen;
|
||||
if (offScreen && !m_offScreenRender)
|
||||
{
|
||||
// offscreen render requested, create the offscreen render buffer
|
||||
m_offScreenRender = m_rasterizer->CreateOffScreen(m_canvas->GetWidth(), m_canvas->GetHeight(), 0, RAS_IOffScreen::RAS_OFS_RENDER_BUFFER, RAS_IOffScreen::RAS_OFS_COLOR_FLOAT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KX_KetsjiEngine::SetShowFramerate(bool frameRate)
|
||||
{
|
||||
m_show_framerate = frameRate;
|
||||
|
@@ -74,6 +74,7 @@ class KX_KetsjiEngine
|
||||
private:
|
||||
class RAS_ICanvas* m_canvas; // 2D Canvas (2D Rendering Device Context)
|
||||
class RAS_IRasterizer* m_rasterizer; // 3D Rasterizer (3D Rendering)
|
||||
class RAS_IOffScreen* m_offScreenRender; // render in render buffer instead of frame buffer
|
||||
class KX_ISystem* m_kxsystem;
|
||||
class KX_ISceneConverter* m_sceneconverter;
|
||||
class NG_NetworkDeviceInterface* m_networkdevice;
|
||||
@@ -130,6 +131,7 @@ private:
|
||||
static short m_exitkey; /* Key used to exit the BGE */
|
||||
|
||||
static bool m_doRender; /* whether or not the scene should be rendered after the logic frame */
|
||||
static bool m_doOffScreen; /* whether normal render should be sent to an offscreen render buffer or to the frame buffer */
|
||||
|
||||
int m_exitcode;
|
||||
STR_String m_exitstring;
|
||||
@@ -252,7 +254,8 @@ public:
|
||||
///returns true if an update happened to indicate -> Render
|
||||
bool NextFrame();
|
||||
void Render();
|
||||
void RenderShadowBuffers(KX_Scene *scene);
|
||||
bool RenderShadowBuffers(KX_Scene *scene);
|
||||
void BindOffScreen(bool bind);
|
||||
|
||||
void StartEngine(bool clearIpo);
|
||||
void StopEngine();
|
||||
@@ -413,6 +416,11 @@ public:
|
||||
* Get the current render flag value
|
||||
*/
|
||||
static bool GetRender();
|
||||
/**
|
||||
* Activate or deactivates the offscreen render of the scene after the logic frame
|
||||
* \param offScreen true (render to offScreen) or false (render to frame buffer)
|
||||
*/
|
||||
void SetOffScreen(bool offScreen);
|
||||
|
||||
/**
|
||||
* \Sets the display for frame rate on or off.
|
||||
|
@@ -484,6 +484,14 @@ static PyObject *gPyGetRender(PyObject *)
|
||||
return PyBool_FromLong(KX_KetsjiEngine::GetRender());
|
||||
}
|
||||
|
||||
static PyObject *gPySetOffScreen(PyObject *, PyObject *args)
|
||||
{
|
||||
int offScreen;
|
||||
if (!PyArg_ParseTuple(args, "i:setOffScreen", &offScreen))
|
||||
return NULL;
|
||||
gp_KetsjiEngine->SetOffScreen(offScreen);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *gPySetMaxLogicFrame(PyObject *, PyObject *args)
|
||||
{
|
||||
@@ -897,6 +905,15 @@ static PyObject *gPyNextFrame(PyObject *)
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *gPyRender(PyObject *)
|
||||
{
|
||||
if (pynextframestate.render == NULL) Py_RETURN_NONE;
|
||||
if (pynextframestate.state == NULL) Py_RETURN_NONE; //should never happen; raise exception instead?
|
||||
|
||||
pynextframestate.render(pynextframestate.state);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static struct PyMethodDef game_methods[] = {
|
||||
{"expandPath", (PyCFunction)gPyExpandPath, METH_VARARGS, (const char *)gPyExpandPath_doc},
|
||||
@@ -927,6 +944,7 @@ static struct PyMethodDef game_methods[] = {
|
||||
{"setExitKey", (PyCFunction) gPySetExitKey, METH_VARARGS, (const char *)"Sets the key used to exit the game engine"},
|
||||
{"setRender", (PyCFunction) gPySetRender, METH_VARARGS, (const char *)"Set the global render flag"},
|
||||
{"getRender", (PyCFunction) gPyGetRender, METH_NOARGS, (const char *)"get the global render flag value"},
|
||||
{"setOffScreen", (PyCFunction) gPySetOffScreen, METH_VARARGS, (const char *)"Set the global offscreen flag"},
|
||||
{"getUseExternalClock", (PyCFunction) gPyGetUseExternalClock, METH_NOARGS, (const char *)"Get if we use the time provided by an external clock"},
|
||||
{"setUseExternalClock", (PyCFunction) gPySetUseExternalClock, METH_VARARGS, (const char *)"Set if we use the time provided by an external clock"},
|
||||
{"getClockTime", (PyCFunction) gPyGetClockTime, METH_NOARGS, (const char *)"Get the last BGE render time. "
|
||||
@@ -944,6 +962,7 @@ static struct PyMethodDef game_methods[] = {
|
||||
{"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, (const char *)"Prints GL Extension Info"},
|
||||
{"PrintMemInfo", (PyCFunction)pyPrintStats, METH_NOARGS, (const char *)"Print engine statistics"},
|
||||
{"NextFrame", (PyCFunction)gPyNextFrame, METH_NOARGS, (const char *)"Render next frame (if Python has control)"},
|
||||
{"Render", (PyCFunction)gPyRender, METH_NOARGS, (const char *)"Do only render (skip logic), if Python has control"},
|
||||
{"getProfileInfo", (PyCFunction)gPyGetProfileInfo, METH_NOARGS, gPyGetProfileInfo_doc},
|
||||
/* library functions */
|
||||
{"LibLoad", (PyCFunction)gLibLoad, METH_VARARGS|METH_KEYWORDS, (const char *)""},
|
||||
@@ -1520,12 +1539,13 @@ static PyGetSetDef RASOffScreen_getseters[] = {
|
||||
|
||||
static int PyRASOffScreen__tp_init(PyRASOffScreen *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
int width, height, samples, target;
|
||||
const char *keywords[] = {"width", "height", "samples", "target", NULL};
|
||||
int width, height, samples, target, bits;
|
||||
const char *keywords[] = {"width", "height", "samples", "target", "bits", NULL};
|
||||
|
||||
samples = 0;
|
||||
target = RAS_IOffScreen::RAS_OFS_RENDER_BUFFER;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|ii:RASOffscreen", (char **)keywords, &width, &height, &samples, &target)) {
|
||||
bits = RAS_IOffScreen::RAS_OFS_COLOR_8BITS;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|iii:RASOffscreen", (char **)keywords, &width, &height, &samples, &target, &bits)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1549,12 +1569,17 @@ static int PyRASOffScreen__tp_init(PyRASOffScreen *self, PyObject *args, PyObjec
|
||||
PyErr_SetString(PyExc_ValueError, "invalid 'target' given, can only be RAS_OFS_RENDER_BUFFER or RAS_OFS_RENDER_TEXTURE");
|
||||
return -1;
|
||||
}
|
||||
if (bits != RAS_IOffScreen::RAS_OFS_COLOR_8BITS && bits != RAS_IOffScreen::RAS_OFS_COLOR_FLOAT)
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "invalid 'bits' given, can only be RAS_OFS_COLOR_8BITS or RAS_OFS_COLOR_FLOAT");
|
||||
return -1;
|
||||
}
|
||||
if (!gp_Rasterizer)
|
||||
{
|
||||
PyErr_SetString(PyExc_SystemError, "no rasterizer");
|
||||
return -1;
|
||||
}
|
||||
self->ofs = gp_Rasterizer->CreateOffScreen(width, height, samples, target);
|
||||
self->ofs = gp_Rasterizer->CreateOffScreen(width, height, samples, target, bits);
|
||||
if (!self->ofs) {
|
||||
PyErr_SetString(PyExc_SystemError, "creation failed");
|
||||
return -1;
|
||||
@@ -1619,9 +1644,10 @@ static PyObject *gPyOffScreenCreate(PyObject *UNUSED(self), PyObject *args)
|
||||
int height;
|
||||
int samples;
|
||||
int target;
|
||||
int bits
|
||||
|
||||
samples = 0;
|
||||
if (!PyArg_ParseTuple(args, "ii|ii:offScreenCreate", &width, &height, &samples, &target))
|
||||
if (!PyArg_ParseTuple(args, "ii|iii:offScreenCreate", &width, &height, &samples, &target, &bits))
|
||||
return NULL;
|
||||
|
||||
return PyObject_CallObject((PyObject *) &PyRASOffScreen_Type, args);
|
||||
|
@@ -78,12 +78,15 @@ KX_Scene *KX_GetActiveScene();
|
||||
KX_KetsjiEngine *KX_GetActiveEngine();
|
||||
|
||||
typedef int (*PyNextFrameFunc)(void *);
|
||||
typedef void (*PyRenderFunc)(void *);
|
||||
|
||||
struct PyNextFrameState {
|
||||
/** can be either a GPG_NextFrameState or a BL_KetsjiNextFrameState */
|
||||
void *state;
|
||||
/** can be either GPG_PyNextFrame or BL_KetsjiPyNextFrame */
|
||||
PyNextFrameFunc func;
|
||||
/** can be either GPG_PyRender or BL_KetsjiPyRender */
|
||||
PyRenderFunc render;
|
||||
};
|
||||
extern struct PyNextFrameState pynextframestate;
|
||||
|
||||
|
@@ -2152,9 +2152,9 @@ bool KX_Scene::MergeScene(KX_Scene *other)
|
||||
return true;
|
||||
}
|
||||
|
||||
void KX_Scene::Update2DFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text)
|
||||
void KX_Scene::Update2DFilter(vector<STR_String>& propNames, void* gameObj, void *mat, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text)
|
||||
{
|
||||
m_filtermanager.EnableFilter(propNames, gameObj, filtermode, pass, text);
|
||||
m_filtermanager.EnableFilter(propNames, gameObj, mat, filtermode, pass, text);
|
||||
}
|
||||
|
||||
void KX_Scene::Render2DFilters(RAS_ICanvas* canvas)
|
||||
|
@@ -82,6 +82,7 @@ class RAS_MaterialBucket;
|
||||
class RAS_IPolyMaterial;
|
||||
class RAS_IRasterizer;
|
||||
class RAS_IRenderTools;
|
||||
class RAS_MeshObject;
|
||||
class SCA_JoystickManager;
|
||||
class btCollisionShape;
|
||||
class KX_BlenderSceneConverter;
|
||||
@@ -607,7 +608,7 @@ public:
|
||||
/**
|
||||
* 2D Filters
|
||||
*/
|
||||
void Update2DFilter(std::vector<STR_String>& propNames, void* gameObj, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text);
|
||||
void Update2DFilter(std::vector<STR_String>& propNames, void* gameObj, void *mat, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text);
|
||||
void Render2DFilters(RAS_ICanvas* canvas);
|
||||
|
||||
KX_ObstacleSimulation* GetObstacleSimulation() { return m_obstacleSimulation; }
|
||||
|
@@ -41,14 +41,27 @@
|
||||
#include "RAS_ICanvas.h"
|
||||
#include "RAS_Rect.h"
|
||||
#include "RAS_2DFilterManager.h"
|
||||
#include "RAS_MaterialBucket.h"
|
||||
#include "BL_Material.h"
|
||||
#include <iostream>
|
||||
|
||||
#include "DNA_image_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "glew-mx.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "EXP_Value.h"
|
||||
|
||||
#define MAX_OBJ_TEXTURE 5
|
||||
static const char *objTextureName[MAX_OBJ_TEXTURE] = {
|
||||
"bgl_ObjectTexture0",
|
||||
"bgl_ObjectTexture1",
|
||||
"bgl_ObjectTexture2",
|
||||
"bgl_ObjectTexture3",
|
||||
"bgl_ObjectTexture4"
|
||||
};
|
||||
|
||||
RAS_2DFilterManager::RAS_2DFilterManager():
|
||||
texturewidth(-1), textureheight(-1),
|
||||
/* numberoffilters(0), */ /* UNUSED */ need_tex_update(true)
|
||||
@@ -67,6 +80,7 @@ texturewidth(-1), textureheight(-1),
|
||||
m_enabled[passindex] = 0;
|
||||
texflag[passindex] = 0;
|
||||
m_gameObjects[passindex] = NULL;
|
||||
m_blmat[passindex] = NULL;
|
||||
}
|
||||
texname[0] = texname[1] = texname[2] = -1;
|
||||
errorprinted= false;
|
||||
@@ -217,6 +231,19 @@ void RAS_2DFilterManager::AnalyseShader(int passindex, vector<STR_String>& propN
|
||||
if (glGetUniformLocationARB(m_filters[passindex], propNames[i]) != -1)
|
||||
m_properties[passindex].push_back(propNames[i]);
|
||||
}
|
||||
if (m_blmat[passindex])
|
||||
{
|
||||
BL_Material *mat = (BL_Material *)m_blmat[passindex];
|
||||
m_textures[passindex].resize(MAX_OBJ_TEXTURE);
|
||||
for (int i=0; i<MAX_OBJ_TEXTURE; i++)
|
||||
{
|
||||
m_textures[passindex][i] = NULL;
|
||||
if (i < MAXTEX && glGetUniformLocationARB(m_filters[passindex], objTextureName[i]) != -1)
|
||||
{
|
||||
m_textures[passindex][i] = mat->img[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RAS_2DFilterManager::StartShaderProgram(int passindex)
|
||||
@@ -224,35 +251,35 @@ void RAS_2DFilterManager::StartShaderProgram(int passindex)
|
||||
GLint uniformLoc;
|
||||
glUseProgramObjectARB(m_filters[passindex]);
|
||||
uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_RenderedTexture");
|
||||
glActiveTextureARB(GL_TEXTURE0);
|
||||
glActiveTextureARB(GL_TEXTURE5);
|
||||
glBindTexture(GL_TEXTURE_2D, texname[0]);
|
||||
|
||||
if (uniformLoc != -1)
|
||||
{
|
||||
glUniform1iARB(uniformLoc, 0);
|
||||
glUniform1iARB(uniformLoc, 5);
|
||||
}
|
||||
|
||||
/* send depth texture to glsl program if it needs */
|
||||
if (texflag[passindex] & 0x1) {
|
||||
uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_DepthTexture");
|
||||
glActiveTextureARB(GL_TEXTURE1);
|
||||
glActiveTextureARB(GL_TEXTURE6);
|
||||
glBindTexture(GL_TEXTURE_2D, texname[1]);
|
||||
|
||||
if (uniformLoc != -1)
|
||||
{
|
||||
glUniform1iARB(uniformLoc, 1);
|
||||
glUniform1iARB(uniformLoc, 6);
|
||||
}
|
||||
}
|
||||
|
||||
/* send luminance texture to glsl program if it needs */
|
||||
if (texflag[passindex] & 0x2) {
|
||||
uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_LuminanceTexture");
|
||||
glActiveTextureARB(GL_TEXTURE2);
|
||||
glActiveTextureARB(GL_TEXTURE7);
|
||||
glBindTexture(GL_TEXTURE_2D, texname[2]);
|
||||
|
||||
if (uniformLoc != -1)
|
||||
{
|
||||
glUniform1iARB(uniformLoc, 2);
|
||||
glUniform1iARB(uniformLoc, 7);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,6 +323,23 @@ void RAS_2DFilterManager::StartShaderProgram(int passindex)
|
||||
break;
|
||||
}
|
||||
}
|
||||
int objTextures = m_textures[passindex].size();
|
||||
for (i=0; i<objTextures; i++)
|
||||
{
|
||||
Image *img;
|
||||
unsigned int bindcode;
|
||||
if ((img = m_textures[passindex][i]) != NULL && (bindcode = img->bindcode[TEXTARGET_TEXTURE_2D]) != 0)
|
||||
{
|
||||
uniformLoc = glGetUniformLocationARB(m_filters[passindex], objTextureName[i]);
|
||||
glActiveTextureARB(GL_TEXTURE0+i);
|
||||
glBindTexture(GL_TEXTURE_2D, bindcode);
|
||||
|
||||
if (uniformLoc != -1)
|
||||
{
|
||||
glUniform1iARB(uniformLoc, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RAS_2DFilterManager::EndShaderProgram()
|
||||
@@ -315,6 +359,7 @@ void RAS_2DFilterManager::FreeTextures()
|
||||
|
||||
void RAS_2DFilterManager::SetupTextures(bool depth, bool luminance)
|
||||
{
|
||||
GLenum error;
|
||||
FreeTextures();
|
||||
|
||||
glGenTextures(1, (GLuint*)&texname[0]);
|
||||
@@ -354,8 +399,8 @@ void RAS_2DFilterManager::SetupTextures(bool depth, bool luminance)
|
||||
void RAS_2DFilterManager::UpdateOffsetMatrix(RAS_ICanvas* canvas)
|
||||
{
|
||||
/* RAS_Rect canvas_rect = canvas->GetWindowArea(); */ /* UNUSED */
|
||||
texturewidth = canvas->GetWidth()+1;
|
||||
textureheight = canvas->GetHeight()+1;
|
||||
texturewidth = canvas->GetWidth();
|
||||
textureheight = canvas->GetHeight();
|
||||
GLint i,j;
|
||||
|
||||
if (!GL_ARB_texture_non_power_of_two)
|
||||
@@ -443,13 +488,13 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
|
||||
}
|
||||
|
||||
if (need_depth) {
|
||||
glActiveTextureARB(GL_TEXTURE1);
|
||||
glActiveTextureARB(GL_TEXTURE6);
|
||||
glBindTexture(GL_TEXTURE_2D, texname[1]);
|
||||
glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, viewport[0], viewport[1], viewport[2], viewport[3], 0);
|
||||
}
|
||||
|
||||
if (need_luminance) {
|
||||
glActiveTextureARB(GL_TEXTURE2);
|
||||
glActiveTextureARB(GL_TEXTURE7);
|
||||
glBindTexture(GL_TEXTURE_2D, texname[2]);
|
||||
glCopyTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE16, viewport[0], viewport[1], viewport[2], viewport[3], 0);
|
||||
}
|
||||
@@ -463,8 +508,8 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
|
||||
|
||||
glScissor(scissor_rect.GetLeft() + viewport[0],
|
||||
scissor_rect.GetBottom() + viewport[1],
|
||||
scissor_rect.GetWidth() + 1,
|
||||
scissor_rect.GetHeight() + 1);
|
||||
scissor_rect.GetWidth(),
|
||||
scissor_rect.GetHeight());
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
// in case the previous material was wire
|
||||
@@ -488,9 +533,9 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
|
||||
{
|
||||
StartShaderProgram(passindex);
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0);
|
||||
glActiveTextureARB(GL_TEXTURE5);
|
||||
glBindTexture(GL_TEXTURE_2D, texname[0]);
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, viewport[0], viewport[1], viewport[2], viewport[3], 0); // Don't use texturewidth and textureheight in case we don't have NPOT support
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, viewport[0], viewport[1], viewport[2], viewport[3], 0); // Don't use texturewidth and textureheight in case we don't have NPOT support
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
@@ -502,6 +547,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
glActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
EndShaderProgram();
|
||||
@@ -510,7 +556,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void RAS_2DFilterManager::EnableFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFILTER_MODE mode, int pass, STR_String& text)
|
||||
void RAS_2DFilterManager::EnableFilter(vector<STR_String>& propNames, void* gameObj, void *mat, RAS_2DFILTER_MODE mode, int pass, STR_String& text)
|
||||
{
|
||||
if (!isshadersupported)
|
||||
return;
|
||||
@@ -536,7 +582,9 @@ void RAS_2DFilterManager::EnableFilter(vector<STR_String>& propNames, void* game
|
||||
m_enabled[pass] = 0;
|
||||
m_filters[pass] = 0;
|
||||
m_gameObjects[pass] = NULL;
|
||||
m_blmat[pass] = NULL;
|
||||
m_properties[pass].clear();
|
||||
m_textures[pass].clear();
|
||||
texflag[pass] = 0;
|
||||
return;
|
||||
}
|
||||
@@ -547,6 +595,7 @@ void RAS_2DFilterManager::EnableFilter(vector<STR_String>& propNames, void* game
|
||||
glDeleteObjectARB(m_filters[pass]);
|
||||
m_filters[pass] = CreateShaderProgram(text.Ptr());
|
||||
m_gameObjects[pass] = gameObj;
|
||||
m_blmat[pass] = mat;
|
||||
AnalyseShader(pass, propNames);
|
||||
m_enabled[pass] = 1;
|
||||
return;
|
||||
@@ -557,6 +606,7 @@ void RAS_2DFilterManager::EnableFilter(vector<STR_String>& propNames, void* game
|
||||
glDeleteObjectARB(m_filters[pass]);
|
||||
m_filters[pass] = CreateShaderProgram(mode);
|
||||
m_gameObjects[pass] = NULL;
|
||||
m_blmat[pass] = NULL;
|
||||
AnalyseShader(pass, propNames);
|
||||
m_enabled[pass] = 1;
|
||||
}
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#endif
|
||||
|
||||
class RAS_ICanvas;
|
||||
struct Image;
|
||||
|
||||
class RAS_2DFilterManager
|
||||
{
|
||||
@@ -78,6 +79,10 @@ private:
|
||||
// stores object properties to send to shaders in each pass
|
||||
std::vector<STR_String> m_properties[MAX_RENDER_PASS];
|
||||
void* m_gameObjects[MAX_RENDER_PASS];
|
||||
void *m_blmat[MAX_RENDER_PASS];
|
||||
// stores the additional textures that should be mapped during render pass to GL_TEXTURE3..7
|
||||
std::vector<struct Image *> m_textures[MAX_RENDER_PASS];
|
||||
|
||||
public:
|
||||
enum RAS_2DFILTER_MODE {
|
||||
RAS_2DFILTER_ENABLED = -2,
|
||||
@@ -104,7 +109,7 @@ public:
|
||||
|
||||
void RenderFilters(RAS_ICanvas* canvas);
|
||||
|
||||
void EnableFilter(std::vector<STR_String>& propNames, void* gameObj, RAS_2DFILTER_MODE mode, int pass, STR_String& text);
|
||||
void EnableFilter(std::vector<STR_String>& propNames, void* gameObj, void *mat, RAS_2DFILTER_MODE mode, int pass, STR_String& text);
|
||||
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
|
@@ -51,6 +51,10 @@ public:
|
||||
RAS_OFS_RENDER_BUFFER = 0, // use render buffer as render target
|
||||
RAS_OFS_RENDER_TEXTURE, // use texture as render target
|
||||
};
|
||||
enum RAS_OFS_COLOR_BITS {
|
||||
RAS_OFS_COLOR_8BITS = 0, // color buffer will be 8bits unsigned per color
|
||||
RAS_OFS_COLOR_FLOAT, // color buffer will be 32bits float per color (if OpenGL supports it)
|
||||
};
|
||||
|
||||
int m_width;
|
||||
int m_height;
|
||||
@@ -59,7 +63,7 @@ public:
|
||||
|
||||
virtual ~RAS_IOffScreen() {}
|
||||
|
||||
virtual bool Create(int width, int height, int samples, RAS_OFS_RENDER_TARGET target) = 0;
|
||||
virtual bool Create(int width, int height, int samples, RAS_OFS_RENDER_TARGET target, RAS_OFS_COLOR_BITS bits) = 0;
|
||||
virtual void Destroy() = 0;
|
||||
virtual void Bind(RAS_OFS_BIND_MODE mode) = 0;
|
||||
virtual void Blit() = 0;
|
||||
|
@@ -263,7 +263,7 @@ public:
|
||||
* Create an offscreen render buffer that can be used as target for render.
|
||||
* For the time being, it is only used in VideoTexture for custom render.
|
||||
*/
|
||||
virtual RAS_IOffScreen *CreateOffScreen(int width, int height, int samples, int target) = 0;
|
||||
virtual RAS_IOffScreen *CreateOffScreen(int width, int height, int samples, int target, int bits) = 0;
|
||||
|
||||
/**
|
||||
* Create a sync object
|
||||
|
@@ -47,7 +47,7 @@ RAS_OpenGLOffScreen::~RAS_OpenGLOffScreen()
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool RAS_OpenGLOffScreen::Create(int width, int height, int samples, RAS_OFS_RENDER_TARGET target)
|
||||
bool RAS_OpenGLOffScreen::Create(int width, int height, int samples, RAS_OFS_RENDER_TARGET target, RAS_OFS_COLOR_BITS bits)
|
||||
{
|
||||
GLenum status;
|
||||
GLuint glo[2], fbo;
|
||||
@@ -111,7 +111,10 @@ bool RAS_OpenGLOffScreen::Create(int width, int height, int samples, RAS_OFS_REN
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_depthtx);
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_DEPTH_COMPONENT, width, height, true);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_colortx);
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, width, height, true);
|
||||
if (bits == RAS_OFS_COLOR_FLOAT && GLEW_ARB_texture_float)
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, width, height, true);
|
||||
else
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA32F, width, height, true);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
@@ -123,7 +126,10 @@ bool RAS_OpenGLOffScreen::Create(int width, int height, int samples, RAS_OFS_REN
|
||||
glBindTexture(GL_TEXTURE_2D, m_depthtx);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_2D, m_colortx);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
if (bits == RAS_OFS_COLOR_FLOAT && GLEW_ARB_texture_float)
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
|
||||
@@ -141,7 +147,10 @@ bool RAS_OpenGLOffScreen::Create(int width, int height, int samples, RAS_OFS_REN
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER, m_depthrb);
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT, width, height);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER, m_colorrb);
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_RGBA8, width, height);
|
||||
if (bits == RAS_OFS_COLOR_FLOAT && GLEW_ARB_texture_float)
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_RGBA32F, width, height);
|
||||
else
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_RGBA8, width, height);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
|
||||
@@ -180,7 +189,10 @@ bool RAS_OpenGLOffScreen::Create(int width, int height, int samples, RAS_OFS_REN
|
||||
// m_color is the texture where the final render goes, the blit texture in this case
|
||||
m_color = m_blittex = blit_tex;
|
||||
glBindTexture(GL_TEXTURE_2D, m_blittex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
if (bits == RAS_OFS_COLOR_FLOAT && GLEW_ARB_texture_float)
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
@@ -198,7 +210,10 @@ bool RAS_OpenGLOffScreen::Create(int width, int height, int samples, RAS_OFS_REN
|
||||
}
|
||||
m_blitrbo = blit_tex;
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER, m_blitrbo);
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 0, GL_RGBA8, width, height);
|
||||
if (bits == RAS_OFS_COLOR_FLOAT && GLEW_ARB_texture_float)
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 0, GL_RGBA32F, width, height);
|
||||
else
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 0, GL_RGBA8, width, height);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_blitfbo);
|
||||
glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER, m_blitrbo);
|
||||
|
@@ -53,7 +53,7 @@ public:
|
||||
RAS_OpenGLOffScreen(RAS_ICanvas *canvas);
|
||||
~RAS_OpenGLOffScreen();
|
||||
|
||||
bool Create(int width, int height, int samples, RAS_OFS_RENDER_TARGET target);
|
||||
bool Create(int width, int height, int samples, RAS_OFS_RENDER_TARGET target, RAS_OFS_COLOR_BITS bits);
|
||||
void Destroy();
|
||||
void Bind(RAS_OFS_BIND_MODE mode);
|
||||
void Blit();
|
||||
|
@@ -601,13 +601,13 @@ float RAS_OpenGLRasterizer::GetFocalLength()
|
||||
return m_focallength;
|
||||
}
|
||||
|
||||
RAS_IOffScreen *RAS_OpenGLRasterizer::CreateOffScreen(int width, int height, int samples, int target)
|
||||
RAS_IOffScreen *RAS_OpenGLRasterizer::CreateOffScreen(int width, int height, int samples, int target, int bits)
|
||||
{
|
||||
RAS_IOffScreen *ofs;
|
||||
|
||||
ofs = new RAS_OpenGLOffScreen(m_2DCanvas);
|
||||
|
||||
if (!ofs->Create(width, height, samples, (RAS_IOffScreen::RAS_OFS_RENDER_TARGET)target)) {
|
||||
if (!ofs->Create(width, height, samples, (RAS_IOffScreen::RAS_OFS_RENDER_TARGET)target, (RAS_IOffScreen::RAS_OFS_COLOR_BITS)bits)) {
|
||||
delete ofs;
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -181,7 +181,7 @@ public:
|
||||
virtual float GetEyeSeparation();
|
||||
virtual void SetFocalLength(const float focallength);
|
||||
virtual float GetFocalLength();
|
||||
virtual RAS_IOffScreen *CreateOffScreen(int width, int height, int samples, int target);
|
||||
virtual RAS_IOffScreen *CreateOffScreen(int width, int height, int samples, int target, int bits);
|
||||
virtual RAS_ISync *CreateSync(int type);
|
||||
virtual void SwapBuffers();
|
||||
|
||||
|
@@ -118,6 +118,26 @@ unsigned int * ImageBase::getImage (unsigned int texId, double ts)
|
||||
return m_avail ? m_image : NULL;
|
||||
}
|
||||
|
||||
unsigned int ImageBase::getPixelSize(unsigned int format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GL_RGBA:
|
||||
case GL_BGRA:
|
||||
case GL_DEPTH_COMPONENT32F:
|
||||
return 4;
|
||||
case GL_RGBA32F:
|
||||
return 4*4;
|
||||
case GL_RGB32F:
|
||||
return 3*4;
|
||||
case GL_RG32F:
|
||||
return 2*4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool ImageBase::loadImage(unsigned int *buffer, unsigned int size, unsigned int format, double ts)
|
||||
{
|
||||
unsigned int *d, *s, v, len;
|
||||
@@ -564,6 +584,14 @@ PyObject *Image_refresh (PyImage *self, PyObject *args)
|
||||
format = GL_RGBA;
|
||||
else if (!strcmp(mode, "BGRA"))
|
||||
format = GL_BGRA;
|
||||
else if (!strcmp(mode, "DEPTH"))
|
||||
format = GL_DEPTH_COMPONENT32F;
|
||||
else if (!strcmp(mode, "RGBA32F"))
|
||||
format = GL_RGBA32F;
|
||||
else if (!strcmp(mode, "RGB32F"))
|
||||
format = GL_RGB32F;
|
||||
else if (!strcmp(mode, "RG32F"))
|
||||
format = GL_RG32F;
|
||||
else
|
||||
THRWEXCP(InvalidImageMode,S_OK);
|
||||
|
||||
|
@@ -70,8 +70,9 @@ public:
|
||||
/// get image size
|
||||
short * getSize(void) { return m_size; }
|
||||
/// get image buffer size
|
||||
unsigned long getBuffSize(void)
|
||||
unsigned long getBuffSize()
|
||||
{ return m_size[0] * m_size[1] * sizeof(unsigned int); }
|
||||
unsigned int getPixelSize(unsigned int format);
|
||||
/// refresh image - invalidate its current content
|
||||
virtual void refresh(void);
|
||||
|
||||
|
@@ -134,7 +134,7 @@ void ImageRender::setBackgroundFromScene (KX_Scene *scene)
|
||||
|
||||
|
||||
// capture image from viewport
|
||||
void ImageRender::calcViewport (unsigned int texId, double ts, unsigned int format)
|
||||
void ImageRender::calcImage (unsigned int texId, double ts)
|
||||
{
|
||||
// render the scene from the camera
|
||||
if (!m_done) {
|
||||
@@ -148,12 +148,34 @@ void ImageRender::calcViewport (unsigned int texId, double ts, unsigned int form
|
||||
// wait until all render operations are completed
|
||||
WaitSync();
|
||||
// get image from viewport (or FBO)
|
||||
ImageViewport::calcViewport(texId, ts, format);
|
||||
calcViewport(texId, ts);
|
||||
if (m_offscreen) {
|
||||
m_offscreen->ofs->Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageRender::loadImage(unsigned int *buffer, unsigned int size, unsigned int format, double ts)
|
||||
{
|
||||
bool ret;
|
||||
// render the scene from the camera
|
||||
if (!m_done) {
|
||||
if (!Render()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (m_offscreen) {
|
||||
m_offscreen->ofs->Bind(RAS_IOffScreen::RAS_OFS_BIND_READ);
|
||||
}
|
||||
// wait until all render operations are completed
|
||||
WaitSync();
|
||||
// get image from viewport (or FBO)
|
||||
ret = loadRender(buffer, size, format);
|
||||
if (m_offscreen) {
|
||||
m_offscreen->ofs->Unbind();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ImageRender::Render()
|
||||
{
|
||||
RAS_FrameFrustum frustum;
|
||||
@@ -246,7 +268,7 @@ bool ImageRender::Render()
|
||||
m_canvas->UpdateViewPort(0, 0, m_offscreen->ofs->GetWidth(), m_offscreen->ofs->GetHeight());
|
||||
}
|
||||
else {
|
||||
m_canvas->SetViewPort(m_position[0], m_position[1], m_position[0]+m_capSize[0]-1, m_position[1]+m_capSize[1]-1);
|
||||
m_canvas->SetViewPort(m_position[0], m_position[1], m_position[0]+m_capSize[0], m_position[1]+m_capSize[1]);
|
||||
}
|
||||
m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]);
|
||||
m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
|
||||
|
@@ -73,6 +73,8 @@ public:
|
||||
void Unbind();
|
||||
/// wait for render to complete
|
||||
void WaitSync();
|
||||
/// load render buffer directly into user image
|
||||
virtual bool loadImage(unsigned int *buffer, unsigned int size, unsigned int format, double ts);
|
||||
|
||||
protected:
|
||||
/// true if ready to render
|
||||
@@ -111,10 +113,7 @@ protected:
|
||||
|
||||
|
||||
/// render 3d scene to image
|
||||
virtual void calcImage (unsigned int texId, double ts) { calcViewport(texId, ts, GL_RGBA); }
|
||||
|
||||
/// render 3d scene to image
|
||||
virtual void calcViewport (unsigned int texId, double ts, unsigned int format);
|
||||
virtual void calcImage (unsigned int texId, double ts);
|
||||
|
||||
void setBackgroundFromScene(KX_Scene *scene);
|
||||
void SetWorldSettings(KX_WorldInfo* wi);
|
||||
|
@@ -132,9 +132,15 @@ void ImageViewport::setPosition (GLint pos[2])
|
||||
m_upLeft[idx] = m_position[idx] + m_viewport[idx];
|
||||
}
|
||||
|
||||
void ImageViewport::calcImage (unsigned int texId, double ts)
|
||||
{
|
||||
KX_GetActiveEngine()->BindOffScreen(true);
|
||||
calcViewport(texId, ts);
|
||||
KX_GetActiveEngine()->BindOffScreen(false);
|
||||
}
|
||||
|
||||
// capture image from viewport
|
||||
void ImageViewport::calcViewport (unsigned int texId, double ts, unsigned int format)
|
||||
void ImageViewport::calcViewport (unsigned int texId, double ts)
|
||||
{
|
||||
// if scale was changed
|
||||
if (m_scaleChange)
|
||||
@@ -192,12 +198,12 @@ void ImageViewport::calcViewport (unsigned int texId, double ts, unsigned int fo
|
||||
!m_flip &&
|
||||
!m_pyfilter)
|
||||
{
|
||||
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], format,
|
||||
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, m_image);
|
||||
m_avail = true;
|
||||
}
|
||||
else if (!m_pyfilter) {
|
||||
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], format,
|
||||
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, m_viewportImage);
|
||||
FilterRGBA32 filt;
|
||||
filterImage(filt, m_viewportImage, m_capSize);
|
||||
@@ -207,10 +213,6 @@ void ImageViewport::calcViewport (unsigned int texId, double ts, unsigned int fo
|
||||
GL_UNSIGNED_BYTE, m_viewportImage);
|
||||
FilterRGBA32 filt;
|
||||
filterImage(filt, m_viewportImage, m_capSize);
|
||||
if (format == GL_BGRA) {
|
||||
// in place byte swapping
|
||||
swapImageBR();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -219,10 +221,6 @@ void ImageViewport::calcViewport (unsigned int texId, double ts, unsigned int fo
|
||||
// filter loaded data
|
||||
FilterRGB24 filt;
|
||||
filterImage(filt, m_viewportImage, m_capSize);
|
||||
if (format == GL_BGRA) {
|
||||
// in place byte swapping
|
||||
swapImageBR();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,35 +229,55 @@ void ImageViewport::calcViewport (unsigned int texId, double ts, unsigned int fo
|
||||
|
||||
bool ImageViewport::loadImage(unsigned int *buffer, unsigned int size, unsigned int format, double ts)
|
||||
{
|
||||
unsigned int *tmp_image;
|
||||
bool ret;
|
||||
|
||||
// if scale was changed
|
||||
if (m_scaleChange) {
|
||||
// reset image
|
||||
init(m_capSize[0], m_capSize[1]);
|
||||
}
|
||||
|
||||
// size must be identical
|
||||
if (size < getBuffSize())
|
||||
return false;
|
||||
|
||||
if (m_avail) {
|
||||
// just copy
|
||||
return ImageBase::loadImage(buffer, size, format, ts);
|
||||
}
|
||||
else {
|
||||
tmp_image = m_image;
|
||||
m_image = buffer;
|
||||
calcViewport(0, ts, format);
|
||||
ret = m_avail;
|
||||
m_image = tmp_image;
|
||||
// since the image was not loaded to our buffer, it's not valid
|
||||
m_avail = false;
|
||||
}
|
||||
KX_GetActiveEngine()->BindOffScreen(true);
|
||||
ret = loadRender(buffer, size, format);
|
||||
KX_GetActiveEngine()->BindOffScreen(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ImageViewport::loadRender(unsigned int *buffer, unsigned int size, unsigned int format)
|
||||
{
|
||||
unsigned int renderSize;
|
||||
|
||||
renderSize = getPixelSize(format)*m_capSize[0]*m_capSize[1];
|
||||
if (renderSize == 0)
|
||||
return false;
|
||||
|
||||
// size must be identical
|
||||
if (size < renderSize)
|
||||
return false;
|
||||
|
||||
switch (format) {
|
||||
case GL_DEPTH_COMPONENT32F:
|
||||
// Use read pixels with the depth buffer
|
||||
// See warning above about m_viewportImage.
|
||||
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1],
|
||||
GL_DEPTH_COMPONENT, GL_FLOAT, buffer);
|
||||
break;
|
||||
case GL_RGBA:
|
||||
case GL_BGRA:
|
||||
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1],
|
||||
format, GL_UNSIGNED_BYTE, buffer);
|
||||
break;
|
||||
case GL_RGBA32F:
|
||||
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1],
|
||||
GL_RGBA, GL_FLOAT, buffer);
|
||||
break;
|
||||
case GL_RGB32F:
|
||||
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1],
|
||||
GL_RGB, GL_FLOAT, buffer);
|
||||
break;
|
||||
case GL_RG32F:
|
||||
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1],
|
||||
GL_RG, GL_FLOAT, buffer);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// cast Image pointer to ImageViewport
|
||||
inline ImageViewport * getImageViewport (PyImage *self)
|
||||
|
@@ -93,10 +93,13 @@ protected:
|
||||
bool m_texInit;
|
||||
|
||||
/// capture image from viewport
|
||||
virtual void calcImage (unsigned int texId, double ts) { calcViewport(texId, ts, GL_RGBA); }
|
||||
virtual void calcImage (unsigned int texId, double ts);
|
||||
|
||||
/// capture image from viewport
|
||||
virtual void calcViewport (unsigned int texId, double ts, unsigned int format);
|
||||
virtual void calcViewport (unsigned int texId, double ts);
|
||||
|
||||
/// read render buffer to user buffer
|
||||
virtual bool loadRender(unsigned int *buffer, unsigned int size, unsigned int format);
|
||||
|
||||
/// get viewport size
|
||||
GLint * getViewportSize (void) { return m_viewport + 2; }
|
||||
|
Reference in New Issue
Block a user