Blender Internal Render in viewport

Because of our release soon, feature has been added behind the Debug Menu.
CTRL+ALT+D and set it to -1. Or commandline --debug-value -1.

When debug set to -1, you can put the viewport to 'render' mode, just like
for Cycles. Notes for testers: (and please no bugs in tracker for this :)

- It renders without AA, MBlur, Panorama, Sequence, Composite
- Only active render layer gets rendered. Select another layer will re-render.
- But yes: it works for FreeStyle renders!
- Also does great for local view.
- BI is not well suited for incremental renders on view changes. This only
  works for non-raytrace scenes, or zoom in ortho or camera mode, or for 
  Material changes. In most cases a full re-render is being done.
- ESC works to stop the preview render.
- Borders render as well. (CTRL+B)
- Force a refresh with arrow key left/right. A lot of settings don't trigger
  re-render yet.

Tech notes:

- FreeStyle is adding a lot of temp objects/meshes in the Main database. This
caused DepsGraph to trigger changes (and redraws). I've prepended the names
for these temp objects with char number 27 (ESC), and made these names be
ignored for tag update checking.

- Fixed some bugs that were noticable with such excessive re-renders, like 
  for opening file window, quit during renders.
This commit is contained in:
Ton Roosendaal 2013-04-16 17:39:20 +00:00
parent 6dcee054be
commit ae58968e0a
Notes: blender-bot 2023-02-14 02:22:07 +01:00
Referenced by commit 75d49b7f55, Removed a Freestyle hack for DAG updates introduced in commit rBae58968e0a61.
23 changed files with 565 additions and 51 deletions

View File

@ -2341,7 +2341,8 @@ void DAG_ids_check_recalc(Main *bmain, Scene *scene, int time)
/* we tag based on first ID type character to avoid
* looping over all ID's in case there are no tags */
if (id && bmain->id_tag_update[id->name[0]]) {
/* XXX very weak... added check for '27' to ignore freestyle added objects */
if (id && id->name[2] > 27 && bmain->id_tag_update[id->name[0]]) {
updated = 1;
break;
}

View File

@ -122,6 +122,8 @@ void mul_v4d_m4v4d(double r[4], float M[4][4], double v[4]);
void transpose_m3(float R[3][3]);
void transpose_m4(float R[4][4]);
int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit);
void normalize_m3(float R[3][3]);
void normalize_m3_m3(float R[3][3], float A[3][3]);
void normalize_m4(float R[4][4]);

View File

@ -722,6 +722,16 @@ void transpose_m4(float mat[4][4])
mat[3][2] = t;
}
int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit)
{
if (compare_v4v4(mat1[0], mat2[0], limit))
if (compare_v4v4(mat1[1], mat2[1], limit))
if (compare_v4v4(mat1[2], mat2[2], limit))
if (compare_v4v4(mat1[3], mat2[3], limit))
return 1;
return 0;
}
void orthogonalize_m3(float mat[3][3], int axis)
{
float size[3];

View File

@ -6209,9 +6209,9 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
v3d->properties_storage = NULL;
v3d->defmaterial = NULL;
/* render can be quite heavy, set to wire on load */
/* render can be quite heavy, set to solid on load */
if (v3d->drawtype == OB_RENDER)
v3d->drawtype = OB_WIRE;
v3d->drawtype = OB_SOLID;
blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
}

View File

@ -38,6 +38,8 @@ struct Render;
struct RenderInfo;
struct Scene;
struct ScrArea;
struct RegionView3D;
struct RenderEngine;
/* render_ops.c */
@ -85,4 +87,6 @@ void ED_preview_draw(const struct bContext *C, void *idp, void *parentp, void *s
void ED_render_clear_mtex_copybuf(void);
void ED_render_internal_init(void);
#endif

View File

@ -83,6 +83,8 @@ void TEXTURE_OT_envmap_clear_all(struct wmOperatorType *ot);
/* render_internal.c */
void RENDER_OT_render(struct wmOperatorType *ot);
void render_view3d(struct RenderEngine *engine, const struct bContext *C);
void render_view3d_draw(struct RenderEngine *engine, const struct bContext *C);
/* render_opengl.c uses this */
void image_buffer_rect_update(struct Scene *scene, struct RenderResult *rr, struct ImBuf *ibuf, volatile struct rcti *renrect);

View File

@ -42,9 +42,11 @@
#include "BLF_translation.h"
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_freestyle.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_library.h"
@ -59,14 +61,23 @@
#include "WM_api.h"
#include "WM_types.h"
#include "ED_screen.h"
#include "ED_object.h"
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "RE_pipeline.h"
#include "RE_engine.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "GPU_extensions.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "RNA_access.h"
#include "RNA_define.h"
@ -681,3 +692,352 @@ void RENDER_OT_render(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************** preview for 3d viewport ***************** */
#define PR_UPDATE_VIEW 1
#define PR_UPDATE_RENDERSIZE 2
#define PR_UPDATE_MATERIAL 4
typedef struct RenderPreview {
/* from wmJob */
void *owner;
short *stop, *do_update;
Scene *scene;
ScrArea *sa;
ARegion *ar;
View3D *v3d;
RegionView3D *rv3d;
Main *bmain;
RenderEngine *engine;
int keep_data;
} RenderPreview;
static int render_view3d_disprect(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, rcti *disprect)
{
/* copied code from view3d_draw.c */
rctf viewborder;
int draw_border;
if (rv3d->persp == RV3D_CAMOB)
draw_border = (scene->r.mode & R_BORDER) != 0;
else
draw_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
if (draw_border) {
if (rv3d->persp == RV3D_CAMOB) {
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
disprect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
disprect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
disprect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
disprect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
}
else {
disprect->xmin = v3d->render_border.xmin * ar->winx;
disprect->xmax = v3d->render_border.xmax * ar->winx;
disprect->ymin = v3d->render_border.ymin * ar->winy;
disprect->ymax = v3d->render_border.ymax * ar->winy;
}
return 1;
}
BLI_rcti_init(disprect, 0, 0, 0, 0);
return 0;
}
/* returns 1 if OK */
static int render_view3d_get_rects(ARegion *ar, View3D *v3d, RegionView3D *rv3d, rctf *viewplane, RenderEngine *engine, float *clipsta, float *clipend, int *ortho)
{
if (ar->winx < 4 || ar->winy < 4) return 0;
*ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, viewplane, clipsta, clipend);
engine->resolution_x = ar->winx;
engine->resolution_y = ar->winy;
return 1;
}
/* called by renderer, checks job value */
static int render_view3d_break(void *rpv)
{
RenderPreview *rp = rpv;
if (G.is_break)
return 1;
/* during render, rv3d->engine can get freed */
if (rp->rv3d->render_engine == NULL)
*rp->stop = 1;
return *(rp->stop);
}
static void render_view3d_draw_update(void *rpv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
{
RenderPreview *rp = rpv;
*(rp->do_update) = TRUE;
}
static void render_view3d_renderinfo_cb(void *rjp, RenderStats *rs)
{
RenderPreview *rp = rjp;
/* during render, rv3d->engine can get freed */
if (rp->rv3d->render_engine == NULL)
*rp->stop = 1;
else if (rp->engine->text) {
make_renderinfo_string(rs, rp->scene, rp->engine->text);
/* make jobs timer to send notifier */
*(rp->do_update) = TRUE;
}
}
static void render_view3d_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
{
RenderPreview *rp = customdata;
Render *re;
RenderStats *rstats;
RenderData rdata;
rctf viewplane;
rcti cliprct;
float clipsta, clipend;
int orth, restore = 0;
char name[32];
G.is_break = FALSE;
if (0 == render_view3d_get_rects(rp->ar, rp->v3d, rp->rv3d, &viewplane, rp->engine, &clipsta, &clipend, &orth))
return;
rp->stop = stop;
rp->do_update = do_update;
// printf("Enter previewrender\n");
/* ok, are we rendering all over? */
sprintf(name, "View3dPreview %p", (void *)rp->ar);
re= rp->engine->re = RE_GetRender(name);
if (rp->engine->re == NULL) {
re = rp->engine->re= RE_NewRender(name);
rp->keep_data = 0;
}
/* set this always, rp is different for each job */
RE_test_break_cb(re, rp, render_view3d_break);
RE_display_draw_cb(re, rp, render_view3d_draw_update);
RE_stats_draw_cb(re, rp, render_view3d_renderinfo_cb);
rstats= RE_GetStats(re);
if (rp->keep_data == 0 || rstats->convertdone == 0 || (rp->keep_data & PR_UPDATE_RENDERSIZE)) {
/* no osa, blur, seq, layers, etc for preview render */
rdata = rp->scene->r;
rdata.mode &= ~(R_OSA | R_MBLUR | R_BORDER | R_PANORAMA);
rdata.scemode &= ~(R_DOSEQ | R_DOCOMP | R_FREE_IMAGE);
rdata.scemode |= R_PREVIEWBUTS;
/* we do use layers, but only active */
rdata.scemode |= R_SINGLE_LAYER;
/* initalize always */
if (render_view3d_disprect(rp->scene, rp->ar, rp->v3d, rp->rv3d, &cliprct)) {
rdata.mode |= R_BORDER;
RE_InitState(re, NULL, &rdata, NULL, rp->sa->winx, rp->sa->winy, &cliprct);
}
else
RE_InitState(re, NULL, &rdata, NULL, rp->sa->winx, rp->sa->winy, NULL);
}
if (orth)
RE_SetOrtho(re, &viewplane, clipsta, clipend);
else
RE_SetWindow(re, &viewplane, clipsta, clipend);
/* database free can crash on a empty Render... */
if (rp->keep_data == 0 && rstats->convertdone)
RE_Database_Free(re);
if (rstats->convertdone == 0) {
unsigned int lay = rp->scene->lay;
/* allow localview render for objects with lights in normal layers */
if (rp->v3d->lay & 0xFF000000)
lay |= rp->v3d->lay;
else lay = rp->v3d->lay;
RE_SetView(re, rp->rv3d->viewmat);
RE_Database_FromScene(re, rp->bmain, rp->scene, lay, 0); // 0= dont use camera view
// printf("dbase update\n");
}
else {
// printf("dbase rotate\n");
RE_DataBase_IncrementalView(re, rp->rv3d->viewmat, 0);
restore = 1;
}
RE_DataBase_ApplyWindow(re);
/* OK, can we enter render code? */
if (rstats->convertdone) {
RE_TileProcessor(re);
// printf("tile processor\n");
if (restore)
RE_DataBase_IncrementalView(re, rp->rv3d->viewmat, 1);
rp->engine->flag &= ~RE_ENGINE_DO_UPDATE;
}
// printf("done\n\n");
}
static void render_view3d_free(void *customdata)
{
RenderPreview *rp = customdata;
MEM_freeN(rp);
}
static void render_view3d_do(RenderEngine *engine, const bContext *C, int keep_data)
{
wmJob *wm_job;
RenderPreview *rp;
Scene *scene = CTX_data_scene(C);
if (CTX_wm_window(C) == NULL) {
engine->flag |= RE_ENGINE_DO_UPDATE;
return;
}
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_wm_region(C), "Render Preview",
WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW);
rp = MEM_callocN(sizeof(RenderPreview), "render preview");
/* customdata for preview thread */
rp->scene = scene;
rp->engine = engine;
rp->sa = CTX_wm_area(C);
rp->ar = CTX_wm_region(C);
rp->v3d = rp->sa->spacedata.first;
rp->rv3d = CTX_wm_region_view3d(C);
rp->bmain = CTX_data_main(C);
rp->keep_data = keep_data;
/* dont alloc in threads */
if (engine->text == NULL)
engine->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext");
/* setup job */
WM_jobs_customdata_set(wm_job, rp, render_view3d_free);
WM_jobs_timer(wm_job, 0.1, NC_SPACE|ND_SPACE_VIEW3D, NC_SPACE|ND_SPACE_VIEW3D);
WM_jobs_callbacks(wm_job, render_view3d_startjob, NULL, NULL, NULL);
WM_jobs_start(CTX_wm_manager(C), wm_job);
engine->flag &= ~RE_ENGINE_DO_UPDATE;
}
/* callback for render engine , on changes */
void render_view3d(RenderEngine *engine, const bContext *C)
{
render_view3d_do(engine, C, 0);
}
static int render_view3d_changed(RenderEngine *engine, const bContext *C)
{
ARegion *ar = CTX_wm_region(C);
Render *re;
int update = 0;
char name[32];
sprintf(name, "View3dPreview %p", (void *)ar);
re = RE_GetRender(name);
if (re) {
RegionView3D *rv3d = CTX_wm_region_view3d(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
rctf viewplane, viewplane1;
rcti disprect, disprect1;
float mat[4][4];
float clipsta, clipend;
int orth;
if (engine->update_flag == RE_ENGINE_UPDATE_MA)
update |= PR_UPDATE_MATERIAL;
engine->update_flag = 0;
if (engine->resolution_x != ar->winx || engine->resolution_y != ar->winy)
update |= PR_UPDATE_RENDERSIZE;
/* view updating fails on raytrace */
RE_GetView(re, mat);
if (compare_m4m4(mat, rv3d->viewmat, 0.00001f) == 0) {
if ((scene->r.mode & R_RAYTRACE)==0)
update |= PR_UPDATE_VIEW;
else
engine->flag |= RE_ENGINE_DO_UPDATE;
}
render_view3d_get_rects(ar, v3d, rv3d, &viewplane, engine, &clipsta, &clipend, &orth);
RE_GetViewPlane(re, &viewplane1, &disprect1);
if (BLI_rctf_compare(&viewplane, &viewplane1, 0.00001f) == 0)
update |= PR_UPDATE_VIEW;
render_view3d_disprect(scene, ar, v3d, rv3d, &disprect);
if (BLI_rcti_compare(&disprect, &disprect1) == 0)
update |= PR_UPDATE_RENDERSIZE;
if (update)
engine->flag |= RE_ENGINE_DO_UPDATE;
// if (update)
// printf("changed ma %d res %d view %d\n", update & PR_UPDATE_MATERIAL, update & PR_UPDATE_RENDERSIZE, update & PR_UPDATE_VIEW);
}
return update;
}
void render_view3d_draw(RenderEngine *engine, const bContext *C)
{
Render *re = engine->re;
RenderResult rres;
int keep_data = render_view3d_changed(engine, C);
if (engine->flag & RE_ENGINE_DO_UPDATE)
render_view3d_do(engine, C, keep_data);
if (re == NULL) return;
RE_AcquireResultImage(re, &rres);
RE_ReleaseResultImage(re);
if (rres.rectf) {
unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
RE_ResultGet32(re, (unsigned int *)rect_byte);
glEnable(GL_BLEND);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, rect_byte);
glDisable(GL_BLEND);
MEM_freeN(rect_byte);
}
}

View File

@ -93,7 +93,6 @@
#include "RE_pipeline.h"
#include "WM_api.h"
#include "WM_types.h"

View File

@ -116,6 +116,7 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
engine = rv3d->render_engine;
if (engine && (updated || (engine->flag & RE_ENGINE_DO_UPDATE))) {
CTX_wm_screen_set(C, sc);
CTX_wm_area_set(C, sa);
CTX_wm_region_set(C, ar);
@ -177,6 +178,32 @@ void ED_render_engine_changed(Main *bmain)
* editor level updates when the ID changes. when these ID blocks are in *
* the dependency graph, we can get rid of the manual dependency checks */
static void render_engine_flag_changed(Main *bmain, int update_flag)
{
bScreen *sc;
ScrArea *sa;
ARegion *ar;
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
for (sa = sc->areabase.first; sa; sa = sa->next) {
if (sa->spacetype != SPACE_VIEW3D)
continue;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
RegionView3D *rv3d;
if (ar->regiontype != RGN_TYPE_WINDOW)
continue;
rv3d = ar->regiondata;
if (rv3d->render_engine)
rv3d->render_engine->update_flag |= update_flag;
}
}
}
}
static int mtex_use_tex(MTex **mtex, int tot, Tex *tex)
{
int a;
@ -472,6 +499,7 @@ void ED_render_id_flush_update(Main *bmain, ID *id)
switch (GS(id->name)) {
case ID_MA:
material_changed(bmain, (Material *)id);
render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_MA);
break;
case ID_TE:
texture_changed(bmain, (Tex *)id);
@ -487,9 +515,21 @@ void ED_render_id_flush_update(Main *bmain, ID *id)
break;
case ID_SCE:
scene_changed(bmain, (Scene *)id);
render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_OTHER);
break;
default:
render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_OTHER);
break;
}
}
void ED_render_internal_init(void)
{
RenderEngineType *ret = RE_engines_find("BLENDER_RENDER");
ret->view_update = render_view3d;
ret->view_draw = render_view3d_draw;
}

View File

@ -149,6 +149,8 @@ void ED_spacetypes_init(void)
type->dropboxes();
}
/* register internal render callbacks */
ED_render_internal_init();
}
/* called in wm.c */

View File

@ -199,7 +199,8 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera
sms.to_camera = true; /* restore view3d values in end */
}
if (C && U.smooth_viewtx) {
/* skip smooth viewing for render engine draw */
if (C && U.smooth_viewtx && v3d->drawtype != OB_RENDER) {
bool changed = false; /* zero means no difference */
if (oldcamera != camera)

View File

@ -478,9 +478,11 @@ Object *BlenderStrokeRenderer::NewMesh() const
char name[MAX_ID_NAME];
unsigned int mesh_id = get_stroke_mesh_id();
BLI_snprintf(name, MAX_ID_NAME, "0%08xOB", mesh_id);
/* XXX this is for later review, for now we start names with 27 (DEL)
to allow ignoring them in DAG_ids_check_recalc() */
BLI_snprintf(name, MAX_ID_NAME, "%c0%08xOB", 27, mesh_id);
ob = BKE_object_add_only_object(G.main, OB_MESH, name);
BLI_snprintf(name, MAX_ID_NAME, "0%08xME", mesh_id);
BLI_snprintf(name, MAX_ID_NAME, "%c0%08xME", 27, mesh_id);
ob->data = BKE_mesh_add(G.main, name);
ob->lay = 1;
@ -491,7 +493,7 @@ Object *BlenderStrokeRenderer::NewMesh() const
#else
(void)base;
#endif
ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
ob->recalc = OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
return ob;
}

View File

@ -66,6 +66,10 @@ struct Scene;
#define RE_ENGINE_HIGHLIGHT_TILES 32
#define RE_ENGINE_USED_FOR_VIEWPORT 64
/* RenderEngine.update_flag, used by internal now */
#define RE_ENGINE_UPDATE_MA 1
#define RE_ENGINE_UPDATE_OTHER 2
extern ListBase R_engines;
typedef struct RenderEngineType {
@ -92,7 +96,7 @@ typedef struct RenderEngine {
RenderEngineType *type;
void *py_instance;
int flag;
int flag, update_flag;
struct Object *camera_override;
int tile_x;

View File

@ -197,12 +197,18 @@ void RE_SetPixelSize(struct Render *re, float pixsize);
/* option to set viewmatrix before making dbase */
void RE_SetView(struct Render *re, float mat[4][4]);
/* get current view and window transform */
void RE_GetView(struct Render *re, float mat[4][4]);
void RE_GetViewPlane(struct Render *re, rctf *viewplane, rcti *disprect);
/* make or free the dbase */
void RE_Database_FromScene(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, int use_camera_view);
void RE_Database_Free(struct Render *re);
/* project dbase again, when viewplane/perspective changed */
void RE_DataBase_ApplyWindow(struct Render *re);
/* rotate scene again, for incremental render */
void RE_DataBase_IncrementalView(struct Render *re, float viewmat[4][4], int restore);
/* override the scene setting for amount threads, commandline */
void RE_set_max_threads(int threads);

View File

@ -48,6 +48,7 @@ struct ImagePool;
void make_envmaps(struct Render *re);
int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
void env_rotate_scene(struct Render *re, float mat[4][4], int mode);
#endif /* __ENVMAP_H__ */

View File

@ -40,9 +40,9 @@ struct Object;
void free_sample_tables(Render *re);
void make_sample_tables(Render *re);
void RE_parts_clamp(Render *re);
void RE_parts_init(Render *re, int do_crop);
void RE_parts_free(Render *re);
void RE_parts_clamp(Render *re);
#endif /* __INITRENDER_H__ */

View File

@ -166,6 +166,7 @@ struct Render
float grvec[3]; /* for world */
float imat[3][3]; /* copy of viewinv */
float viewmat[4][4], viewinv[4][4];
float viewmat_orig[4][4]; /* for incremental render */
float winmat[4][4];
/* clippping */

View File

@ -4851,10 +4851,11 @@ void RE_Database_Free(Render *re)
/* free orco */
free_mesh_orco_hash(re);
end_render_materials(re->main);
end_render_textures(re);
free_pointdensities(re);
if (re->main) {
end_render_materials(re->main);
end_render_textures(re);
free_pointdensities(re);
}
free_camera_inside_volumes(re);
@ -5202,14 +5203,17 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int lay, int use_camera_view)
{
Scene *sce;
Object *camera;
float mat[4][4];
float amb[3];
Object *camera= RE_GetCamera(re);
re->main= bmain;
re->scene= scene;
re->lay= lay;
/* scene needs to be set to get camera */
camera= RE_GetCamera(re);
/* per second, per object, stats print this */
re->i.infostr= "Preparing Scene data";
re->i.cfra= scene->r.cfra;
@ -5246,6 +5250,9 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
camera->recalc= OB_RECALC_OB; /* force correct matrix for scaled cameras */
}
/* store for incremental render, viewmat rotates dbase */
copy_m4_m4(re->viewmat_orig, re->viewmat);
init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */
if (re->r.mode & R_RAYTRACE) {
init_render_qmcsampler(re);
@ -5354,6 +5361,23 @@ void RE_DataBase_ApplyWindow(Render *re)
project_renderdata(re, projectverto, 0, 0, 0);
}
/* exported call to rotate render data again, when viewmat changed */
void RE_DataBase_IncrementalView(Render *re, float viewmat[4][4], int restore)
{
float oldviewinv[4][4], tmat[4][4];
invert_m4_m4(oldviewinv, re->viewmat_orig);
/* we have to correct for the already rotated vertexcoords */
mult_m4_m4m4(tmat, viewmat, oldviewinv);
copy_m4_m4(re->viewmat, viewmat);
invert_m4_m4(re->viewinv, re->viewmat);
env_rotate_scene(re, tmat, !restore);
}
void RE_DataBase_GetView(Render *re, float mat[4][4])
{
copy_m4_m4(mat, re->viewmat);

View File

@ -246,10 +246,26 @@ static void envmap_transmatrix(float mat[4][4], int part)
NULL, NULL, NULL,
NULL, NULL, NULL);
}
/* ------------------------------------------------------------------------- */
static void env_set_imats(Render *re)
{
Base *base;
float mat[4][4];
base = re->scene->base.first;
while (base) {
mult_m4_m4m4(mat, re->viewmat, base->object->obmat);
invert_m4_m4(base->object->imat, mat);
base = base->next;
}
}
/* ------------------------------------------------------------------------- */
static void env_rotate_scene(Render *re, float mat[4][4], int mode)
void env_rotate_scene(Render *re, float mat[4][4], int mode)
{
GroupObject *go;
ObjectRen *obr;
@ -328,6 +344,10 @@ static void env_rotate_scene(Render *re, float mat[4][4], int mode)
}
}
if (mode) {
init_render_world(re);
env_set_imats(re);
}
}
/* ------------------------------------------------------------------------- */
@ -395,23 +415,6 @@ static void env_showobjects(Render *re)
/* ------------------------------------------------------------------------- */
static void env_set_imats(Render *re)
{
Base *base;
float mat[4][4];
base = re->scene->base.first;
while (base) {
mult_m4_m4m4(mat, re->viewmat, base->object->obmat);
invert_m4_m4(base->object->imat, mat);
base = base->next;
}
}
/* ------------------------------------------------------------------------- */
static void render_envmap(Render *re, EnvMap *env)
{
/* only the cubemap and planar map is implemented */
@ -454,11 +457,9 @@ static void render_envmap(Render *re, EnvMap *env)
invert_m4_m4(env->imat, tmat);
env_rotate_scene(envre, tmat, 1);
init_render_world(envre);
project_renderdata(envre, projectverto, 0, 0, 1);
env_layerflags(envre, env->notlay);
env_hideobject(envre, env->object);
env_set_imats(envre);
if (re->test_break(re->tbh) == 0) {
RE_TileProcessor(envre);

View File

@ -116,6 +116,18 @@ RenderEngineType *RE_engines_find(const char *idname)
if (!type)
type = &internal_render_type;
/* XXX Hack to make this a debug-only option, remove section to make it available default */
if (type == &internal_render_type) {
static RenderEngineType rtype;
if (type->view_update == NULL)
rtype = internal_render_type;
else if (G.debug_value != -1) {
type = &rtype;
}
}
/* XXX end hack */
return type;
}

View File

@ -328,6 +328,9 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr)
rr->have_combined = (re->result->rectf != NULL);
rr->layers = re->result->layers;
rr->xof = re->disprect.xmin;
rr->yof = re->disprect.ymin;
}
}
}
@ -402,7 +405,10 @@ void RE_FreeRender(Render *re)
BLI_rw_mutex_end(&re->resultmutex);
free_renderdata_tables(re);
/* main dbase can already be invalid now, some database-free code checks it */
re->main = NULL;
RE_Database_Free(re); /* view render can still have full database */
free_sample_tables(re);
render_result_free(re->result);
@ -564,13 +570,9 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
if (re->r.scemode & R_PREVIEWBUTS) {
if (re->result && re->result->rectx == re->rectx && re->result->recty == re->recty) {
/* pass */
}
else {
render_result_free(re->result);
re->result = NULL;
}
/* always fresh, freestyle layers need it */
render_result_free(re->result);
re->result = NULL;
}
else {
@ -580,6 +582,9 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
re->result->rectx = re->rectx;
re->result->recty = re->recty;
}
/* ensure renderdatabase can use part settings correct */
RE_parts_clamp(re);
BLI_rw_mutex_unlock(&re->resultmutex);
@ -627,6 +632,22 @@ void RE_SetView(Render *re, float mat[4][4])
invert_m4_m4(re->viewinv, re->viewmat);
}
void RE_GetViewPlane(Render *re, rctf *viewplane, rcti *disprect)
{
*viewplane = re->viewplane;
/* make disprect zero when no border render, is needed to detect changes in 3d view render */
if (re->r.mode & R_BORDER)
*disprect = re->disprect;
else
BLI_rcti_init(disprect, 0, 0, 0, 0);
}
void RE_GetView(Render *re, float mat[4][4])
{
copy_m4_m4(mat, re->viewmat);
}
/* image and movie output has to move to either imbuf or kernel */
void RE_display_init_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr))
{
@ -1035,18 +1056,37 @@ static void threaded_tile_processor(Render *re)
re->viewplane = viewplane; /* restore viewplane, modified by pano render */
}
#ifdef WITH_FREESTYLE
static void add_freestyle(Render *re);
static void free_all_freestyle_renders(Scene *scene);
#endif
/* currently only called by preview renders and envmap */
void RE_TileProcessor(Render *re)
{
threaded_tile_processor(re);
re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
re->stats_draw(re->sdh, &re->i);
#ifdef WITH_FREESTYLE
/* Freestyle */
if (re->r.mode & R_EDGE_FRS) {
if (!re->test_break(re->tbh)) {
add_freestyle(re);
free_all_freestyle_renders(re->scene);
re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
re->stats_draw(re->sdh, &re->i);
}
}
#endif
}
/* ************ This part uses API, for rendering Blender scenes ********** */
#ifdef WITH_FREESTYLE
static void add_freestyle(Render *re);
#endif
static void do_render_3d(Render *re)
{
float cfra;

View File

@ -569,6 +569,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
}
/* border render; calculate offset for use in compositor. compo is centralized coords */
/* XXX obsolete? I now use it for drawing border render offset (ton) */
rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);

View File

@ -438,6 +438,10 @@ void WM_exit_ext(bContext *C, const short do_python)
BKE_mball_cubeTable_free();
/* render code might still access databases */
RE_FreeAllRender();
RE_engines_exit();
ED_preview_free_dbase(); /* frees a Main dbase, before free_blender! */
if (C && wm)
@ -468,9 +472,6 @@ void WM_exit_ext(bContext *C, const short do_python)
ANIM_keyingset_infos_exit();
RE_FreeAllRender();
RE_engines_exit();
// free_txt_data();