OpenGL Render restored.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 28 Oct 2009 18:03:04 +0000 (18:03 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 28 Oct 2009 18:03:04 +0000 (18:03 +0000)
I tried to make it integrate more with regular render but couldn't
do it well, it still needs a 3D view to take the settings from, and
can't run in a separate thread due to OpenGL.

However, it is now rendering to an offscreen buffer which then gets
displayed in the image window. This requires FBO's to be available, so
a fallback creating a new window is still needed. Currently available
from the Render menu in the top header.

release/scripts/ui/space_info.py
source/blender/editors/include/ED_view3d.h
source/blender/editors/screen/SConscript
source/blender/editors/screen/screen_ops.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/gpu/GPU_extensions.h
source/blender/gpu/intern/gpu_extensions.c
source/blender/gpu/intern/gpu_material.c
source/blender/makesrna/intern/rna_armature.c

index 52d5876a46bd15252911741a7a4e8ae13b3a9652..d62ab5b759d1a1a84ebf2df723245394067f5dfd 100644 (file)
@@ -206,6 +206,11 @@ class INFO_MT_render(bpy.types.Menu):
 
                layout.itemS()
 
+               layout.itemO("screen.opengl_render", text="OpenGL Render Image")
+               layout.item_booleanO("screen.opengl_render", "animation", True, text="OpenGL Render Animation")
+
+               layout.itemS()
+
                layout.itemO("screen.render_view_show")
 
 class INFO_MT_help(bpy.types.Menu):
index be2822d8c49e1d9d726f5d09d1ed97d7725b1d0d..2ec9ddf6c5280f3f9df2c59804389e4353f46a88 100644 (file)
@@ -139,5 +139,9 @@ void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d);
 
 void ED_view3d_scene_layers_update(struct Main *bmain, struct Scene *scene);
 
+int ED_view3d_context_activate(struct bContext *C);
+void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
+       int winx, int winy, float viewmat[][4], float winmat[][4]);
+
 #endif /* ED_VIEW3D_H */
 
index 847a1cddfb47ac5222840c7883a8ad7e32c6bd9d..afd6ce68b683781ba5143607b775b282a091aef8 100644 (file)
@@ -4,7 +4,7 @@ Import ('env')
 sources = env.Glob('*.c')
 
 incs = '../include ../../blenlib ../../blenkernel ../../blenfont ../../makesdna ../../imbuf'
-incs += ' ../../blenloader ../../windowmanager ../../python ../../makesrna'
+incs += ' ../../blenloader ../../windowmanager ../../python ../../makesrna ../../gpu'
 incs += ' ../../render/extern/include'
 incs += ' #/intern/guardedalloc #/extern/glew/include'
 
index e65ad221501305c781665e3673a027c3b3a4ca40..a1537b2ddf5739bd1b8ab2c1eace56cc793987ee 100644 (file)
@@ -25,6 +25,9 @@
  */
 
 #include <math.h>
+#include <string.h>
+
+#include <GL/glew.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -41,6 +44,7 @@
 #include "DNA_curve_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_meta_types.h"
+#include "DNA_view3d_types.h"
 
 #include "BKE_blender.h"
 #include "BKE_colortools.h"
@@ -58,6 +62,7 @@
 #include "BKE_screen.h"
 #include "BKE_utildefines.h"
 #include "BKE_sound.h"
+#include "BKE_writeavi.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -68,6 +73,7 @@
 #include "ED_object.h"
 #include "ED_screen_types.h"
 #include "ED_keyframes_draw.h"
+#include "ED_view3d.h"
 
 #include "RE_pipeline.h"
 #include "IMB_imbuf.h"
@@ -79,6 +85,8 @@
 #include "UI_interface.h"
 #include "UI_resources.h"
 
+#include "GPU_extensions.h"
+
 #include "wm_window.h"
 
 #include "screen_intern.h"     /* own module include */
@@ -2756,7 +2764,7 @@ static void image_renderinfo_cb(void *rjv, RenderStats *rs)
 }
 
 /* called inside thread! */
-static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
+static void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
 {
        float x1, y1, *rectf= NULL;
        int ymin, ymax, xmin, xmax;
@@ -2817,7 +2825,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
        rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin);
 
        /* XXX make nice consistent functions for this */
-       if (rj->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
+       if (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)) {
                for(y1= 0; y1<ymax; y1++) {
                        float *rf= rectf;
                        float srgb[3];
@@ -2858,8 +2866,6 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
                }
        }
        
-       /* make jobs timer to send notifier */
-       *(rj->do_update)= 1;
 }
 
 static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
@@ -2869,8 +2875,12 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
        void *lock;
        
        ibuf= BKE_image_acquire_ibuf(rj->image, &rj->iuser, &lock);
-       if(ibuf)
-               image_buffer_rect_update(rj, rr, ibuf, renrect);
+       if(ibuf) {
+               image_buffer_rect_update(rj->scene, rr, ibuf, renrect);
+
+               /* make jobs timer to send notifier */
+               *(rj->do_update)= 1;
+       }
        BKE_image_release_ibuf(rj->image, lock);
 }
 
@@ -3008,7 +3018,301 @@ static void SCREEN_OT_render(wmOperatorType *ot)
        
        ot->poll= ED_operator_screenactive;
        
-       RNA_def_int(ot->srna, "layers", 0, 0, INT_MAX, "Layers", "", 0, INT_MAX);
+       RNA_def_boolean(ot->srna, "animation", 0, "Animation", "");
+}
+
+/* ****************************** opengl render *************************** */
+
+typedef struct OGLRender {
+       Render *re;
+       Scene *scene;
+
+       View3D *v3d;
+       RegionView3D *rv3d;
+       ARegion *ar;
+
+       Image *ima;
+       ImageUser iuser;
+
+       GPUOffScreen *ofs;
+       int sizex, sizey;
+
+       bMovieHandle *mh;
+       int cfrao, nfra;
+
+       wmTimer *timer;
+} OGLRender;
+
+static void screen_opengl_render_apply(OGLRender *oglrender)
+{
+       Scene *scene= oglrender->scene;
+       ARegion *ar= oglrender->ar;
+       View3D *v3d= oglrender->v3d;
+       RegionView3D *rv3d= oglrender->rv3d;
+       RenderResult *rr;
+       ImBuf *ibuf;
+       void *lock;
+       float winmat[4][4];
+       int sizex= oglrender->sizex;
+       int sizey= oglrender->sizey;
+
+       /* bind */
+       GPU_offscreen_bind(oglrender->ofs);
+
+       /* render 3d view */
+       if(rv3d->persp==RV3D_CAMOB && v3d->camera) {
+               RE_GetCameraWindow(oglrender->re, v3d->camera, scene->r.cfra, winmat);
+               ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat);
+       }
+       else
+               ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL);
+
+       /* read in pixels & stamp */
+       rr= RE_AcquireResultRead(oglrender->re);
+       glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, rr->rectf);
+       if((scene->r.scemode & R_STAMP_INFO) && (scene->r.stamp & R_STAMP_DRAW))
+               BKE_stamp_buf(scene, (unsigned char *)rr->rect32, rr->rectf, rr->rectx, rr->recty, 3);
+       RE_ReleaseResult(oglrender->re);
+
+       /* update byte from float buffer */
+       ibuf= BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
+       if(ibuf) image_buffer_rect_update(NULL, rr, ibuf, NULL);
+       BKE_image_release_ibuf(oglrender->ima, lock);
+
+       /* unbind */
+       GPU_offscreen_unbind(oglrender->ofs);
+}
+
+static int screen_opengl_render_init(bContext *C, wmOperator *op)
+{
+       /* new render clears all callbacks */
+       Scene *scene= CTX_data_scene(C);
+       RenderResult *rr;
+       GPUOffScreen *ofs;
+       OGLRender *oglrender;
+       int sizex, sizey;
+
+       /* ensure we have a 3d view */
+       if(!ED_view3d_context_activate(C))
+               return 0;
+       
+       /* only one render job at a time */
+       if(WM_jobs_test(CTX_wm_manager(C), scene))
+               return 0;
+       
+       /* stop all running jobs, currently previews frustrate Render */
+       WM_jobs_stop_all(CTX_wm_manager(C));
+       
+       /* handle UI stuff */
+       WM_cursor_wait(1);
+
+       /* create offscreen buffer */
+       sizex= (scene->r.size*scene->r.xsch)/100;
+       sizey= (scene->r.size*scene->r.ysch)/100;
+
+       view3d_operator_needs_opengl(C);
+       ofs= GPU_offscreen_create(sizex, sizey);
+
+       if(!ofs) {
+               BKE_report(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer.");
+               return 0;
+       }
+
+       /* allocate opengl render */
+       oglrender= MEM_callocN(sizeof(OGLRender), "OGLRender");
+       op->customdata= oglrender;
+
+       oglrender->ofs= ofs;
+       oglrender->sizex= sizex;
+       oglrender->sizey= sizey;
+       oglrender->scene= scene;
+
+       oglrender->v3d= CTX_wm_view3d(C);
+       oglrender->ar= CTX_wm_region(C);
+       oglrender->rv3d= CTX_wm_region_view3d(C);
+
+       /* create image and image user */
+       oglrender->ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
+       BKE_image_signal(oglrender->ima, NULL, IMA_SIGNAL_FREE);
+
+       oglrender->iuser.scene= scene;
+       oglrender->iuser.ok= 1;
+
+       /* create render and render result */
+       oglrender->re= RE_NewRender(scene->id.name);
+       RE_InitState(oglrender->re, NULL, &scene->r, sizex, sizey, NULL);
+
+       rr= RE_AcquireResultWrite(oglrender->re);
+       if(rr->rectf==NULL)
+               rr->rectf= MEM_mallocN(sizeof(float)*4*sizex*sizex, "32 bits rects");
+       RE_ReleaseResult(oglrender->re);
+
+       return 1;
+}
+
+static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
+{
+       Scene *scene= oglrender->scene;
+
+       if(oglrender->mh) {
+               if(BKE_imtype_is_movie(scene->r.imtype))
+                       oglrender->mh->end_movie();
+       }
+
+       if(oglrender->timer) {
+               scene->r.cfra= oglrender->cfrao;
+               scene_update_for_newframe(scene, scene->lay);
+
+               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), oglrender->timer);
+       }
+
+       WM_cursor_wait(0);
+       WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, oglrender->scene);
+
+       GPU_offscreen_free(oglrender->ofs);
+
+       MEM_freeN(oglrender);
+}
+
+static int screen_opengl_render_cancel(bContext *C, wmOperator *op)
+{
+       screen_opengl_render_end(C, op->customdata);
+
+       return OPERATOR_CANCELLED;
+}
+
+static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       OGLRender *oglrender= op->customdata;
+       Scene *scene= oglrender->scene;
+       ImBuf *ibuf;
+       void *lock;
+       char name[FILE_MAXDIR+FILE_MAXFILE];
+       unsigned int lay;
+       int ok= 0;
+
+       switch(event->type) {
+               case ESCKEY:
+                       /* cancel */
+                       screen_opengl_render_end(C, op->customdata);
+                       return OPERATOR_FINISHED;
+               case TIMER:
+                       /* render frame? */
+                       if(oglrender->timer == event->customdata)
+                               break;
+               default:
+                       /* nothing to do */
+                       return OPERATOR_RUNNING_MODAL;
+       }
+
+       /* go to next frame */
+       while(CFRA<oglrender->nfra) {
+               if(scene->lay & 0xFF000000)
+                       lay= scene->lay & 0xFF000000;
+               else
+                       lay= scene->lay;
+
+               scene_update_for_newframe(scene, lay);
+               CFRA++;
+       }
+
+       scene_update_for_newframe(scene, scene->lay);
+
+       /* render into offscreen buffer */
+       screen_opengl_render_apply(oglrender);
+       
+       /* save to disk */
+       ibuf= BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
+
+       if(ibuf) {
+               if(BKE_imtype_is_movie(scene->r.imtype)) {
+                       oglrender->mh->append_movie(&scene->r, CFRA, (int*)ibuf->rect, oglrender->sizex, oglrender->sizey);
+                       printf("Append frame %d", scene->r.cfra);
+                       ok= 1;
+               }
+               else {
+                       BKE_makepicstring(scene, name, scene->r.pic, scene->r.cfra, scene->r.imtype);
+                       ok= BKE_write_ibuf(scene, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality);
+                       
+                       if(ok==0) printf("write error: cannot save %s\n", name);
+                       else printf("saved: %s", name);
+               }
+       }
+
+       BKE_image_release_ibuf(oglrender->ima, lock);
+
+       /* movie stats prints have no line break */
+       printf("\n");
+       
+       /* go to next frame */
+       oglrender->nfra += scene->frame_step;
+       scene->r.cfra++;
+
+       WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, oglrender->scene);
+
+       /* stop at the end or on error */
+       if(scene->r.cfra > EFRA || !ok) {
+               screen_opengl_render_end(C, op->customdata);
+               return OPERATOR_FINISHED;
+       }
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+static int screen_opengl_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       int anim= RNA_boolean_get(op->ptr, "animation");
+
+       if(!screen_opengl_render_init(C, op))
+               return OPERATOR_CANCELLED;
+       
+       if(!anim) {
+               /* render image */
+               screen_opengl_render_apply(op->customdata);
+               screen_opengl_render_end(C, op->customdata);
+               screen_set_image_output(C, event->x, event->y);
+
+               return OPERATOR_FINISHED;
+       }
+       else {
+               /* initialize animation */
+               OGLRender *oglrender;
+               Scene *scene;
+
+               oglrender= op->customdata;
+               scene= oglrender->scene;
+
+               oglrender->mh= BKE_get_movie_handle(scene->r.imtype);
+               if(BKE_imtype_is_movie(scene->r.imtype))
+                       oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey);
+
+               oglrender->cfrao= scene->r.cfra;
+               oglrender->nfra= SFRA;
+               scene->r.cfra= SFRA;
+
+               WM_event_add_modal_handler(C, op);
+               oglrender->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+
+               screen_set_image_output(C, event->x, event->y);
+
+               return OPERATOR_RUNNING_MODAL;
+       }
+}
+
+static void SCREEN_OT_opengl_render(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "OpenGL Render";
+       ot->description= "OpenGL render active viewport.";
+       ot->idname= "SCREEN_OT_opengl_render";
+       
+       /* api callbacks */
+       ot->invoke= screen_opengl_render_invoke;
+       ot->modal= screen_opengl_render_modal;
+       ot->cancel= screen_opengl_render_cancel;
+       
+       ot->poll= ED_operator_screenactive;
+       
        RNA_def_boolean(ot->srna, "animation", 0, "Animation", "");
 }
 
@@ -3307,6 +3611,7 @@ void ED_operatortypes_screen(void)
        WM_operatortype_append(SCREEN_OT_render);
        WM_operatortype_append(SCREEN_OT_render_view_cancel);
        WM_operatortype_append(SCREEN_OT_render_view_show);
+       WM_operatortype_append(SCREEN_OT_opengl_render);
 
        /* new/delete */
        WM_operatortype_append(SCREEN_OT_new);
index 487c55bec9bfe7cf45682992c73865c4032d6055..64ea574b0117efe394778191de24700f30c5a5ec 100644 (file)
@@ -1897,28 +1897,23 @@ static CustomDataMask get_viewedit_datamask(bScreen *screen, Scene *scene, Objec
        return mask;
 }
 
-void view3d_main_area_draw(const bContext *C, ARegion *ar)
+static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[][4], float winmat[][4])
 {
-       Scene *scene= CTX_data_scene(C);
-       View3D *v3d = CTX_wm_view3d(C);
-       RegionView3D *rv3d= CTX_wm_region_view3d(C);
-       Scene *sce;
-       Base *base;
-       Object *ob;
-       int retopo= 0, sculptparticle= 0;
-       Object *obact = OBACT;
-       char *grid_unit= NULL;
-       
-       /* from now on all object derived meshes check this */
-       v3d->customdata_mask= get_viewedit_datamask(CTX_wm_screen(C), scene, obact);
-       
-       /* shadow buffers, before we setup matrices */
-       if(draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
-               gpu_update_lamps_shadows(scene, v3d);
+       RegionView3D *rv3d= ar->regiondata;
+
+       /* setup window matrices */
+       if(winmat)
+               Mat4CpyMat4(rv3d->winmat, winmat);
+       else
+               setwinmatrixview3d(ar, v3d, NULL); /* NULL= no pickrect */
        
-       setwinmatrixview3d(ar, v3d, NULL);      /* 0= no pick rect */
-       setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
+       /* setup view matrix */
+       if(viewmat)
+               Mat4CpyMat4(rv3d->viewmat, viewmat);
+       else
+               setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
        
+       /* update utilitity matrices */
        Mat4MulMat4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
        Mat4Invert(rv3d->persinv, rv3d->persmat);
        Mat4Invert(rv3d->viewinv, rv3d->viewmat);
@@ -1939,23 +1934,118 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
                else rv3d->pixsize/= (float)ar->winy;
        }
        
+       /* set for opengl */
+       glMatrixMode(GL_PROJECTION);
+       wmLoadMatrix(rv3d->winmat);
+
+       glMatrixMode(GL_MODELVIEW);
+       wmLoadMatrix(rv3d->viewmat);
+}
+
+void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[][4], float winmat[][4])
+{
+       Scene *sce;
+       Base *base;
+       int bwinx, bwiny;
+
+       wmPushMatrix();
+
+       /* set temporary new size */
+       bwinx= ar->winx;
+       bwiny= ar->winy;
+       ar->winx= winx;
+       ar->winy= winy;
+
+       /* set flags */
+       G.f |= G_RENDER_OGL;
+       GPU_free_images();
+
+       /* set background color */
+       glClearColor(scene->world->horr, scene->world->horg, scene->world->horb, 0.0);
+       glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+       /* setup view matrices */
+       view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
+
+       /* set zbuffer */
        if(v3d->drawtype > OB_WIRE) {
-               float col[3];
-               UI_GetThemeColor3fv(TH_BACK, col);
-               glClearColor(col[0], col[1], col[2], 0.0); 
-               glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
-               
-               glLoadIdentity();
+               v3d->zbuf= TRUE;
+               glEnable(GL_DEPTH_TEST);
        }
-       else {
-               float col[3];
-               UI_GetThemeColor3fv(TH_BACK, col);
-               glClearColor(col[0], col[1], col[2], 0.0);
-               glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+       else
+               v3d->zbuf= FALSE;
+
+       /* draw set first */
+       if(scene->set) {
+               for(SETLOOPER(scene->set, base)) {
+                       if(v3d->lay & base->lay) {
+                               UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
+                               draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR|DRAW_SCENESET);
+                               
+                               if(base->object->transflag & OB_DUPLI)
+                                       draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
+                       }
+               }
        }
        
-       wmLoadMatrix(rv3d->viewmat);
+       /* then draw not selected and the duplis, but skip editmode object */
+       for(base= scene->base.first; base; base= base->next) {
+               if(v3d->lay & base->lay) {
+                       /* dupli drawing */
+                       if(base->object->transflag & OB_DUPLI)
+                               draw_dupli_objects(scene, ar, v3d, base);
+
+                       draw_object(scene, ar, v3d, base, 0);
+               }
+       }
+
+       /* transp and X-ray afterdraw stuff */
+       view3d_draw_transp(scene, ar, v3d);
+       view3d_draw_xray(scene, ar, v3d, 1);    // clears zbuffer if it is used!
+
+       /* cleanup */
+       if(v3d->zbuf) {
+               v3d->zbuf= FALSE;
+               glDisable(GL_DEPTH_TEST);
+       }
+
+       GPU_free_images();
+
+       /* restore size */
+       ar->winx= bwinx;
+       ar->winy= bwiny;
+
+       wmPopMatrix();
+}
+
+void view3d_main_area_draw(const bContext *C, ARegion *ar)
+{
+       Scene *scene= CTX_data_scene(C);
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       Scene *sce;
+       Base *base;
+       Object *ob;
+       float col[3];
+       int retopo= 0, sculptparticle= 0;
+       Object *obact = OBACT;
+       char *grid_unit= NULL;
+       
+       /* from now on all object derived meshes check this */
+       v3d->customdata_mask= get_viewedit_datamask(CTX_wm_screen(C), scene, obact);
        
+       /* shadow buffers, before we setup matrices */
+       if(draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
+               gpu_update_lamps_shadows(scene, v3d);
+
+       /* clear background */
+       UI_GetThemeColor3fv(TH_BACK, col);
+       glClearColor(col[0], col[1], col[2], 0.0); 
+       glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+       
+       /* setup view matrices */
+       view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
+
        if(rv3d->rflag & RV3D_CLIPPING)
                view3d_draw_clipping(rv3d);
        
index 300825bfe7d82be431577721184102e53761c044..e2b22afae6216edb18f278466247783bd4c1f080 100644 (file)
@@ -1559,39 +1559,53 @@ int game_engine_poll(bContext *C)
        return CTX_data_mode_enum(C)==CTX_MODE_OBJECT ? 1:0;
 }
 
-static int game_engine_exec(bContext *C, wmOperator *unused)
+int ED_view3d_context_activate(bContext *C)
 {
-#if GAMEBLENDER == 1
-       Scene *startscene = CTX_data_scene(C);
        bScreen *sc= CTX_wm_screen(C);
-       ScrArea *sa, *prevsa= CTX_wm_area(C);
-       ARegion *ar, *prevar= CTX_wm_region(C);
+       ScrArea *sa= CTX_wm_area(C);
+       ARegion *ar;
        RegionView3D *rv3d;
-       rcti cam_frame;
 
-
-       sa= prevsa;
-       if(sa->spacetype != SPACE_VIEW3D) {
+       if(sa->spacetype != SPACE_VIEW3D)
                for(sa=sc->areabase.first; sa; sa= sa->next)
                        if(sa->spacetype==SPACE_VIEW3D)
                                break;
-       }
 
        if(!sa)
-               return OPERATOR_CANCELLED;
+               return 0;
        
        for(ar=sa->regionbase.first; ar; ar=ar->next)
                if(ar->regiontype == RGN_TYPE_WINDOW)
                        break;
        
        if(!ar)
-               return OPERATOR_CANCELLED;
+               return 0;
        
        // bad context switch ..
        CTX_wm_area_set(C, sa);
        CTX_wm_region_set(C, ar);
        rv3d= ar->regiondata;
 
+       return 1;
+}
+
+static int game_engine_exec(bContext *C, wmOperator *unused)
+{
+#if GAMEBLENDER == 1
+       Scene *startscene = CTX_data_scene(C);
+       ScrArea *sa, *prevsa= CTX_wm_area(C);
+       ARegion *ar, *prevar= CTX_wm_region(C);
+       RegionView3D *rv3d;
+       rcti cam_frame;
+
+       // bad context switch ..
+       if(!ED_view3d_context_activate(C))
+               return OPERATOR_CANCELLED;
+       
+       rv3d= CTX_wm_region_view3d(C);
+       sa= CTX_wm_area(C);
+       ar= CTX_wm_region(C);
+
        view3d_operator_needs_opengl(C);
        
        game_set_commmandline_options(&startscene->gm);
index a910ff9c3e7f1fcd47d55154f21153f6754462b3..c2af4e8fcb187caebe87e4ced3692fe8d4ad4ed0 100644 (file)
@@ -48,6 +48,9 @@ typedef struct GPUTexture GPUTexture;
 struct GPUFrameBuffer;
 typedef struct GPUFrameBuffer GPUFrameBuffer;
 
+struct GPUOffScreen;
+typedef struct GPUOffScreen GPUOffScreen;
+
 struct GPUShader;
 typedef struct GPUShader GPUShader;
 
@@ -107,6 +110,14 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb);
 
 void GPU_framebuffer_restore();
 
+/* GPU OffScreen
+   - wrapper around framebuffer and texture for simple offscreen drawing */
+
+GPUOffScreen *GPU_offscreen_create(int width, int height);
+void GPU_offscreen_free(GPUOffScreen *ofs);
+void GPU_offscreen_bind(GPUOffScreen *ofs);
+void GPU_offscreen_unbind(GPUOffScreen *ofs);
+
 /* GPU Shader
    - only for fragment shaders now
    - must call texture bind before setting a texture as uniform! */
index 5c8157be789327ba98ae1a381c6da658d94b5298..5deef4a52001615e79b2a33537839bc534f22fcc 100644 (file)
@@ -616,7 +616,7 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex)
        }
        else {
                glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-               glReadBuffer(GL_NONE);
+               glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
        }
 
        status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
@@ -727,6 +727,78 @@ void GPU_framebuffer_restore()
        }
 }
 
+/* GPUOffScreen */
+
+struct GPUOffScreen {
+       GPUFrameBuffer *fb;
+       GPUTexture *color;
+       GPUTexture *depth;
+};
+
+GPUOffScreen *GPU_offscreen_create(int width, int height)
+{
+       GPUOffScreen *ofs;
+
+       ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
+
+       ofs->fb = GPU_framebuffer_create();
+       if(!ofs->fb) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+
+       ofs->depth = GPU_texture_create_depth(width, height);
+       if(!ofs->depth) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+
+       if(!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth)) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+
+       ofs->color = GPU_texture_create_2D(width, height, NULL);
+       if(!ofs->color) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+
+       if(!GPU_framebuffer_texture_attach(ofs->fb, ofs->color)) {
+               GPU_offscreen_free(ofs);
+               return NULL;
+       }
+
+       GPU_framebuffer_restore();
+
+       return ofs;
+}
+
+void GPU_offscreen_free(GPUOffScreen *ofs)
+{
+       if(ofs->fb)
+               GPU_framebuffer_free(ofs->fb);
+       if(ofs->color)
+               GPU_texture_free(ofs->color);
+       if(ofs->depth)
+               GPU_texture_free(ofs->depth);
+       
+       MEM_freeN(ofs);
+}
+
+void GPU_offscreen_bind(GPUOffScreen *ofs)
+{
+       glDisable(GL_SCISSOR_TEST);
+       GPU_framebuffer_texture_bind(ofs->fb, ofs->color);
+}
+
+void GPU_offscreen_unbind(GPUOffScreen *ofs)
+{
+       GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
+       GPU_framebuffer_restore();
+       glEnable(GL_SCISSOR_TEST);
+}
+
 /* GPUShader */
 
 struct GPUShader {
index 0dc17da93a1590d96a53bbd733b853da302aac0a..0650a0bfa196ac6c551edabc7177f4a8ed10080c 100644 (file)
@@ -1509,6 +1509,7 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize
        Mat4MulMat4(lamp->persmat, persmat, rangemat);
 
        /* opengl */
+       glDisable(GL_SCISSOR_TEST);
        GPU_framebuffer_texture_bind(lamp->fb, lamp->tex);
 
        /* set matrices */
@@ -1521,6 +1522,7 @@ void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
 {
        GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
        GPU_framebuffer_restore();
+       glEnable(GL_SCISSOR_TEST);
 }
 
 int GPU_lamp_shadow_layer(GPULamp *lamp)
index 889f23e0d391eaf5250cf363f2370c84c00f54ab..96dde18626053e2b4983ea66e2bd7bc915ed0935 100644 (file)
@@ -535,7 +535,7 @@ static void rna_def_edit_bone(BlenderRNA *brna)
        
        srna= RNA_def_struct(brna, "EditBone", NULL);
        RNA_def_struct_sdna(srna, "EditBone");
-       RNA_def_struct_idproperties_func(srna, "rna_Bone_idproperties");
+       RNA_def_struct_idproperties_func(srna, "rna_EditBone_idproperties");
        RNA_def_struct_ui_text(srna, "Edit Bone", "Editmode bone in an Armature datablock.");
        RNA_def_struct_ui_icon(srna, ICON_BONE_DATA);