Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Bolsee <benoit.bolsee@online.be>2008-11-26 20:47:42 +0300
committerBenoit Bolsee <benoit.bolsee@online.be>2008-11-26 20:47:42 +0300
commit6a51ba54cd464ef07bb09f1fa84bd2407ff3e8e7 (patch)
tree27ce0a91617cb08f3039871972df772bf9abfb0d /source/gameengine/VideoTexture/ImageRender.cpp
parent15e193f2535be17a89b5d148155f9ee12a5e142a (diff)
VideoTexture: new ImageRender class for Render To Texture
The new class VideoTexture.ImageRender() is available to perform render to texture in the GE. Constructor: VideoTexture.ImageRender(scene,cam) cam : camera object that will be used for the render. It must be an inactive camera. scene: reference to the scene that will be rendered. The camera must be part of that scene. Returns an object that can be used as a source of a VideoTexture.Texture object Methods: none Attributes: background: 4-tuple representing the background color of the rendering as RGBA color components, each component being an integer between 0 and 255. Default value = [0,0,255,255] (=saturated blue) Note: athough the alpha component can be specified, it is not supported at the moment, the alpha channel of the rendered texture will always be 255. You can however introduce an alpha channel by appending a FilterBlueScreen() filter, it will set the alpha to 0 (transparent) on all pixels that were not rendered. capsize: 2-tuple representing the size of the render area as [x,y] number of pixels. Default value = largest rectangle with power of 2 dimensions that fits in the canvas You may want to reduce the render area to increase performance. For example, a render area of [256,128] is probably sufficient to implement a car inner mirror. For best performance, use power of 2 dimensions and don't set any filter: this allows direct transfer between the GPU frame buffer and texture memory without going through the host. alpha: Boolean indicating if the render alpha channel should be copied to the texture. Default value: False Experimental, do not use. whole: Boolean indicating if the entire canvas should be used for the rendering. Default value: False Note: There is no reason to set this attribute to True: the rendering will in any case be scaled down to the largest rectangle with power of 2 dimensions before transfering to the texture. Attributes inherited from the ImageBase class: image : image binary data, read-only size : [x,y] size of the texture, read-only scale : set to True for fast scale down in case the render area dimensions are not power of 2 flip : set to True for vertical flip. filter: set a post-processing filter on the render. Notes: * Aspect Ratio For consistent results in Blender and Blenderplayer, the same aspect ratio used by Blender to draw the camera viewport (Scene(F10)->Format tab->Size X/Size Y) is also used during the rendering. You can control the portion of the scene that will be rendered by "looking through the camera": the zone inside the outer dotted rectangle will be rendered to the texture. In order to reproduce the scene without X/Y distortion, you must apply the texture on an object or portion of object that has the same aspect ratio. * Order of rendering The rendereing is performed when you call the refresh() method of the parent Texture object. This happens outside the normal frame rendering and will have no effect on it. However, if you want to use ImageViewport and ImageRender at the same time, be sure to refresh the viewport texture before the render texture because the latter will destroy the frame buffer that is used by the former to update the texture. * Scene status The meshes are not updated during the render to texture: the rendered texture is one frame late to the rendered frame with regards to mesh deformation. * Example: cont = GameLogic.getCurrentController() # object that receives the texture obj = contr.getOwner() scene = GameLogic.getCurrentScene() # camera used for the render tvcam = scene.getObjectList()['OBtvcam'] # assume obj has some faces UV assigned to tv.png matID = VideoTexture.materialID(obj, 'IMtv.png') GameLogic.tv = VideoTexture.Texture(obj, matID) GameLogic.tv.source = VideoTexture.ImageRender(scene,tvcam) GameLogic.tv.source.capsize = [256,256] # to render the texture, just call GameLogic.tv.refresh(True) on each frame. You can download a demo game (with a video file) here: http://home.scarlet.be/~tsi46445/blender/VideoTextureDemo.zip For those who have already downloaded the demo, you can just update the blend file: http://home.scarlet.be/~tsi46445/blender/VideoTextureDemo.blend
Diffstat (limited to 'source/gameengine/VideoTexture/ImageRender.cpp')
-rw-r--r--source/gameengine/VideoTexture/ImageRender.cpp171
1 files changed, 112 insertions, 59 deletions
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index a8f7871fa21..ba61f0c33f4 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -25,15 +25,12 @@ http://www.gnu.org/copyleft/lesser.txt.
#include <PyObjectPlus.h>
#include <structmember.h>
-#include <KX_BlenderCanvas.h>
-#include <KX_BlenderRenderTools.h>
-#include <RAS_IRasterizer.h>
-#include <RAS_OpenGLRasterizer.h>
-#include <KX_WorldInfo.h>
-#include <KX_Light.h>
+#include <BIF_gl.h>
-#include "ImageRender.h"
+#include "KX_PythonInit.h"
+#include "DNA_scene_types.h"
+#include "ImageRender.h"
#include "ImageBase.h"
#include "BlendType.h"
#include "Exception.h"
@@ -42,78 +39,126 @@ ExceptionID SceneInvalid, CameraInvalid;
ExpDesc SceneInvalidDesc (SceneInvalid, "Scene object is invalid");
ExpDesc CameraInvalidDesc (CameraInvalid, "Camera object is invalid");
-#if 0 // not yet supported
-
// constructor
-ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) : m_scene(scene),
-m_camera(camera)
+ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) :
+ ImageViewport(),
+ m_scene(scene),
+ m_camera(camera)
{
- // create screen area
- m_area.winrct.xmin = m_upLeft[0];
- m_area.winrct.ymin = m_upLeft[1];
- m_area.winx = m_size[0];
- m_area.winy = m_size[1];
- // create canvas
- m_canvas = new KX_BlenderCanvas(&m_area);
- // create render tools
- m_rendertools = new KX_BlenderRenderTools();
- // create rasterizer
- m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
- m_rasterizer->Init();
// initialize background colour
- setBackground(0, 0, 255);
- // refresh lights
- refreshLights();
+ setBackground(0, 0, 255, 255);
+ // retrieve rendering objects
+ m_engine = KX_GetActiveEngine();
+ m_rasterizer = m_engine->GetRasterizer();
+ m_canvas = m_engine->GetCanvas();
+ m_rendertools = m_engine->GetRenderTools();
}
// destructor
ImageRender::~ImageRender (void)
{
- // release allocated objects
- delete m_rasterizer;
- delete m_rendertools;
- delete m_canvas;
}
// set background color
-void ImageRender::setBackground (unsigned char red, unsigned char green, unsigned char blue)
+void ImageRender::setBackground (int red, int green, int blue, int alpha)
{
- m_background[0] = red;
- m_background[1] = green;
- m_background[2] = blue;
- m_rasterizer->SetBackColor(m_background[0], m_background[1], m_background[2], 1.0);
+ m_background[0] = (red < 0) ? 0.f : (red > 255) ? 1.f : float(red)/255.f;
+ m_background[1] = (green < 0) ? 0.f : (green > 255) ? 1.f : float(green)/255.f;
+ m_background[2] = (blue < 0) ? 0.f : (blue > 255) ? 1.f : float(blue)/255.f;
+ m_background[3] = (alpha < 0) ? 0.f : (alpha > 255) ? 1.f : float(alpha)/255.f;
}
// capture image from viewport
void ImageRender::calcImage (unsigned int texId)
{
- // setup camera
- bool cameraPasive = !m_camera->GetViewport();
- // render scene
- Render();
- // reset camera
- if (cameraPasive) m_camera->EnableViewport(false);
+ if (m_rasterizer->GetDrawingMode() != RAS_IRasterizer::KX_TEXTURED || // no need for texture
+ m_camera->GetViewport() || // camera must be inactive
+ m_camera == m_scene->GetActiveCamera())
+ {
+ // no need to compute texture in non texture rendering
+ m_avail = false;
+ return;
+ }
+ // render the scene from the camera
+ Render();
// get image from viewport
ImageViewport::calcImage(texId);
+ // restore OpenGL state
+ m_canvas->EndFrame();
}
void ImageRender::Render()
{
- //
-}
+ const float ortho = 100.0;
+ const RAS_IRasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode();
+
+ // The screen area that ImageViewport will copy is also the rendering zone
+ 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->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]);
+ m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
+ m_rasterizer->BeginFrame(RAS_IRasterizer::KX_TEXTURED,m_engine->GetClockTime());
+ m_rendertools->BeginFrame(m_rasterizer);
+ m_engine->SetWorldSettings(m_scene->GetWorldInfo());
+ m_rendertools->SetAuxilaryClientInfo(m_scene);
+ m_rasterizer->DisplayFog();
+ // matrix calculation, don't apply any of the stereo mode
+ m_rasterizer->SetStereoMode(RAS_IRasterizer::RAS_STEREO_NOSTEREO);
+ if (m_camera->hasValidProjectionMatrix())
+ {
+ m_rasterizer->SetProjectionMatrix(m_camera->GetProjectionMatrix());
+ } else
+ {
+ RAS_FrameFrustum frustrum;
+ float lens = m_camera->GetLens();
+ bool orthographic = !m_camera->GetCameraData()->m_perspective;
+ float nearfrust = m_camera->GetCameraNear();
+ float farfrust = m_camera->GetCameraFar();
+ float aspect_ratio = 1.0f;
+ Scene *blenderScene = m_scene->GetBlenderScene();
+
+ if (orthographic) {
+ lens *= ortho;
+ nearfrust = (nearfrust + 1.0)*ortho;
+ farfrust *= ortho;
+ }
+ // compute the aspect ratio from frame blender scene settings so that render to texture
+ // works the same in Blender and in Blender player
+ if (blenderScene->r.ysch != 0)
+ aspect_ratio = float(blenderScene->r.xsch) / float(blenderScene->r.ysch);
+
+ RAS_FramingManager::ComputeDefaultFrustum(
+ nearfrust,
+ farfrust,
+ lens,
+ aspect_ratio,
+ frustrum);
+
+ MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix(
+ frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar);
+
+ m_camera->SetProjectionMatrix(projmat);
+ }
-// refresh lights
-void ImageRender::refreshLights (void)
-{
- // clear lights list
- //m_rendertools->RemoveAllLights();
- // set lights
- //for (int idx = 0; idx < scene->GetLightList()->GetCount(); ++idx)
- // m_rendertools->AddLight(((KX_LightObject*)(scene->GetLightList()->GetValue(idx)))->GetLightData());
-}
+ MT_Transform camtrans(m_camera->GetWorldToCamera());
+ if (!m_camera->GetCameraData()->m_perspective)
+ camtrans.getOrigin()[2] *= ortho;
+ MT_Matrix4x4 viewmat(camtrans);
+
+ m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldPosition(),
+ m_camera->GetCameraLocation(), m_camera->GetCameraOrientation());
+ m_camera->SetModelviewMatrix(viewmat);
+ // restore the stereo mode now that the matrix is computed
+ m_rasterizer->SetStereoMode(stereomode);
+
+ // do not update the mesh, we don't want to do it more than once per frame
+ //m_scene->UpdateMeshTransformations();
+ m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera);
+
+ m_scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
+}
// cast Image pointer to ImageRender
@@ -174,26 +219,31 @@ static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds
// get background color
PyObject * getBackground (PyImage * self, void * closure)
{
- return Py_BuildValue("[BBB]", getImageRender(self)->getBackground()[0],
- getImageRender(self)->getBackground()[1], getImageRender(self)->getBackground()[2]);
+ return Py_BuildValue("[BBBB]",
+ getImageRender(self)->getBackground(0),
+ getImageRender(self)->getBackground(1),
+ getImageRender(self)->getBackground(2),
+ getImageRender(self)->getBackground(3));
}
// set color
static int setBackground (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
- if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 3
+ if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 4
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))
- || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2)))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2))
+ || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 3)))
{
- PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints");
+ PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 4 integer between 0 and 255");
return -1;
}
// set background color
getImageRender(self)->setBackground((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
(unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))),
- (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))));
+ (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))),
+ (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 3))));
// success
return 0;
}
@@ -209,6 +259,10 @@ static PyMethodDef imageRenderMethods[] =
static PyGetSetDef imageRenderGetSets[] =
{
{(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL},
+ // attribute from ImageViewport
+ {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of render area", NULL},
+ {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL},
+ {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to render", NULL},
// attributes from ImageBase class
{(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL},
{(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
@@ -264,4 +318,3 @@ PyTypeObject ImageRenderType =
};
-#endif // #if 0