Compare commits
114 Commits
main
...
viewport_e
Author | SHA1 | Date | |
---|---|---|---|
5515e5727b | |||
c1e9df7e79 | |||
2a2d90e6e0 | |||
55e206c580 | |||
761e8ef733 | |||
f43f4f0e89 | |||
6719fb8248 | |||
617fc1f49e | |||
eedd9b70b6 | |||
ccd3fb8ea7 | |||
9ef1a6b2f2 | |||
c28f3e3e0a | |||
78aa9be2ee | |||
d5b99ceb55 | |||
3fa8fad5f1 | |||
7064313ec6 | |||
4f5e9f0857 | |||
7409fddf27 | |||
4557ad66c1 | |||
dc506fba9c | |||
4eb6b35926 | |||
0d8b701e25 | |||
bdfd9ba38a | |||
0ea64c2b9a | |||
9d1336b653 | |||
b7c1d2e898 | |||
268ae6a62b | |||
7d1e7de7be | |||
28f271736b | |||
8a8e29ac6a | |||
a75728341b | |||
da94a7005a | |||
568c8b7b55 | |||
6148295f1a | |||
0790db4f5c | |||
1cfb12ddbf | |||
27fe02f213 | |||
79b8540e66 | |||
fd1036e803 | |||
08cc519e79 | |||
b06999435a | |||
9ca9bb68af | |||
f54d210f26 | |||
e306e99574 | |||
85e9ddd515 | |||
63ab9c1089 | |||
dbf18d88fc | |||
a4c154bc5a | |||
2a189a0546 | |||
376a004b26 | |||
4ca945778f | |||
4d6d8b8c14 | |||
702cb6c403 | |||
c37c50e33f | |||
44e8045ee5 | |||
5467064777 | |||
bd434b92b6 | |||
5373b4a8b1 | |||
ec69df6147 | |||
40b1d29ec7 | |||
3021399869 | |||
ace38bdc82 | |||
cb94f59f71 | |||
63d7d8e1e5 | |||
43d4a56d8d | |||
7b0031b187 | |||
4322085f4f | |||
4aad147fe4 | |||
b550e788f2 | |||
46cc844f43 | |||
7798ecd743 | |||
78d42f7885 | |||
eb8a09d567 | |||
2a5556b426 | |||
de27811177 | |||
6484056cc1 | |||
a4f35de026 | |||
ba2f0ad779 | |||
e0cba973e7 | |||
c6292918a3 | |||
518f794a6f | |||
dc22a50488 | |||
d2d3bd35c1 | |||
0782c680a6 | |||
8f25b6d6c8 | |||
6e8ba2f3f5 | |||
c48abbb090 | |||
5efa0e03b5 | |||
d54c249a7b | |||
3967f5659d | |||
1082a2f125 | |||
ddb33a3181 | |||
33e7e1ddb2 | |||
0c8469c440 | |||
30be0f0977 | |||
e1755158c0 | |||
e963efcd19 | |||
5b4b83d7e3 | |||
5c31594ab7 | |||
c4b6d60af3 | |||
33cee269da | |||
ce9fb0e997 | |||
81a3a364b5 | |||
c56cf0b887 | |||
827ad6075d | |||
d1ed35480e | |||
829addcff0 | |||
313b568f92 | |||
3a0d276c55 | |||
acdaf71bbe | |||
21f43fb13c | |||
2632c1308f | |||
33722d4011 | |||
9e2efd68e1 |
@@ -761,6 +761,11 @@ if B.targets != ['cudakernels']:
|
||||
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex_world.glsl")
|
||||
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl")
|
||||
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl")
|
||||
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl")
|
||||
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl")
|
||||
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl")
|
||||
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_lib.glsl")
|
||||
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_vert.glsl")
|
||||
data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl")
|
||||
|
||||
# --- blender ---
|
||||
|
@@ -177,6 +177,7 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
|
||||
layout = self.layout
|
||||
|
||||
cam = context.camera
|
||||
dof_options = cam.gpu_dof
|
||||
|
||||
layout.label(text="Focus:")
|
||||
|
||||
@@ -187,6 +188,7 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
|
||||
|
||||
col.active = cam.dof_object is None
|
||||
col.prop(cam, "dof_distance", text="Distance")
|
||||
col.prop(dof_options, "fstop", text="GPU fstop")
|
||||
|
||||
|
||||
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
|
||||
|
@@ -2929,8 +2929,26 @@ class VIEW3D_PT_view3d_shading(Panel):
|
||||
col.prop(view, "show_textured_shadeless")
|
||||
|
||||
col.prop(view, "show_backface_culling")
|
||||
if obj and obj.mode == 'EDIT' and view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
|
||||
col.prop(view, "show_occlude_wire")
|
||||
|
||||
if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
|
||||
if obj and obj.mode == 'EDIT':
|
||||
col.prop(view, "show_occlude_wire")
|
||||
|
||||
fx_settings = view.fx_settings
|
||||
|
||||
sub = col.column()
|
||||
sub.active = view.region_3d.view_perspective == 'CAMERA'
|
||||
sub.prop(fx_settings, "use_dof")
|
||||
|
||||
col.prop(fx_settings, "use_ssao", text="Ambient Occlusion")
|
||||
if fx_settings.use_ssao:
|
||||
ssao_settings = fx_settings.ssao
|
||||
subcol = col.column(align=True)
|
||||
subcol.prop(ssao_settings, "factor")
|
||||
subcol.prop(ssao_settings, "distance_max")
|
||||
subcol.prop(ssao_settings, "attenuation")
|
||||
subcol.prop(ssao_settings, "samples")
|
||||
subcol.prop(ssao_settings, "color")
|
||||
|
||||
|
||||
class VIEW3D_PT_view3d_motion_tracking(Panel):
|
||||
|
@@ -46,6 +46,7 @@ set(SRC_DNA_INC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_freestyle_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_genfile.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpu_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_group_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_image_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_ipo_types.h
|
||||
|
@@ -46,6 +46,7 @@ struct RenderData;
|
||||
struct Scene;
|
||||
struct rctf;
|
||||
struct View3D;
|
||||
struct GPUFXSettings;
|
||||
|
||||
/* Camera Datablock */
|
||||
|
||||
@@ -122,6 +123,8 @@ bool BKE_camera_view_frame_fit_to_scene(struct Scene *scene, struct View3D *v3d,
|
||||
bool BKE_camera_view_frame_fit_to_coords(struct Scene *scene, float (*cos)[3], int num_cos,
|
||||
struct Object *camera_ob, float r_co[3], float *r_scale);
|
||||
|
||||
void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -52,6 +52,7 @@ struct wmKeyConfig;
|
||||
struct wmNotifier;
|
||||
struct wmWindow;
|
||||
struct wmWindowManager;
|
||||
struct GPUFXSettings;
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
@@ -294,6 +295,7 @@ void BKE_screen_view3d_scene_sync(struct bScreen *sc);
|
||||
void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene);
|
||||
void BKE_screen_view3d_twmode_remove(struct View3D *v3d, const int i);
|
||||
void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, struct Scene *scene, const int i);
|
||||
void BKE_screen_gpu_fx_validate(struct GPUFXSettings *fx_settings);
|
||||
|
||||
/* zoom factor conversion */
|
||||
float BKE_screen_view3d_zoom_to_fac(float camzoom);
|
||||
|
@@ -49,6 +49,8 @@
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "GPU_compositing.h"
|
||||
|
||||
/****************************** Camera Datablock *****************************/
|
||||
|
||||
void *BKE_camera_add(Main *bmain, const char *name)
|
||||
@@ -66,7 +68,9 @@ void *BKE_camera_add(Main *bmain, const char *name)
|
||||
cam->ortho_scale = 6.0;
|
||||
cam->flag |= CAM_SHOWPASSEPARTOUT;
|
||||
cam->passepartalpha = 0.5f;
|
||||
|
||||
|
||||
GPU_fx_compositor_init_dof_settings(&cam->gpu_dof);
|
||||
|
||||
return cam;
|
||||
}
|
||||
|
||||
@@ -686,3 +690,18 @@ bool BKE_camera_view_frame_fit_to_coords(
|
||||
return camera_frame_fit_calc_from_data(¶ms, &data_cb, r_co, r_scale);
|
||||
}
|
||||
|
||||
void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings)
|
||||
{
|
||||
if (camera->type == OB_CAMERA) {
|
||||
Camera *cam = camera->data;
|
||||
r_fx_settings->dof = &cam->gpu_dof;
|
||||
r_fx_settings->dof->focal_length = cam->lens;
|
||||
r_fx_settings->dof->sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
|
||||
if (cam->dof_ob) {
|
||||
r_fx_settings->dof->focus_distance = len_v3v3(cam->dof_ob->obmat[3], camera->obmat[3]);
|
||||
}
|
||||
else {
|
||||
r_fx_settings->dof->focus_distance = cam->YF_dofdist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -39,6 +39,8 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "GPU_compositing.h"
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
@@ -598,3 +600,26 @@ float BKE_screen_view3d_zoom_from_fac(float zoomfac)
|
||||
{
|
||||
return ((sqrtf(4.0f * zoomfac) - (float)M_SQRT2) * 50.0f);
|
||||
}
|
||||
|
||||
void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
|
||||
{
|
||||
/* currently we use DOF from the camera _only_,
|
||||
* so we never allocate this, only copy from the Camera */
|
||||
#if 0
|
||||
if ((fx_settings->dof == NULL) &&
|
||||
(fx_settings->fx_flag & GPU_FX_FLAG_DOF))
|
||||
{
|
||||
GPUDOFSettings *fx_dof;
|
||||
fx_dof = fx_settings->dof = MEM_callocN(sizeof(GPUDOFSettings), __func__);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fx_settings->ssao == NULL) &&
|
||||
(fx_settings->fx_flag & GPU_FX_FLAG_SSAO))
|
||||
{
|
||||
GPUSSAOSettings *fx_ssao;
|
||||
fx_ssao = fx_settings->ssao = MEM_callocN(sizeof(GPUSSAOSettings), __func__);
|
||||
|
||||
GPU_fx_compositor_init_ssao_settings(fx_ssao);
|
||||
}
|
||||
}
|
||||
|
@@ -6421,6 +6421,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
|
||||
rv3d->render_engine = NULL;
|
||||
rv3d->sms = NULL;
|
||||
rv3d->smooth_timer = NULL;
|
||||
rv3d->compositor = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6528,7 +6529,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
|
||||
/* add local view3d too */
|
||||
else if (sa->spacetype == SPACE_VIEW3D)
|
||||
blo_do_versions_view3d_split_250(sa->spacedata.first, &sa->regionbase);
|
||||
|
||||
|
||||
/* incase we set above */
|
||||
sa->butspacetype = sa->spacetype;
|
||||
|
||||
@@ -6575,6 +6576,11 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
|
||||
/* render can be quite heavy, set to solid on load */
|
||||
if (v3d->drawtype == OB_RENDER)
|
||||
v3d->drawtype = OB_SOLID;
|
||||
|
||||
if (v3d->fx_settings.dof)
|
||||
v3d->fx_settings.dof = newdataadr(fd, v3d->fx_settings.dof);
|
||||
if (v3d->fx_settings.ssao)
|
||||
v3d->fx_settings.ssao = newdataadr(fd, v3d->fx_settings.ssao);
|
||||
|
||||
blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#define DNA_DEPRECATED_ALLOW
|
||||
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_constraint_types.h"
|
||||
#include "DNA_sdna_types.h"
|
||||
@@ -562,6 +563,16 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
}
|
||||
FOREACH_NODETREE_END
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Camera", "GPUDOFSettings", "gpu_dof")) {
|
||||
Camera *ca;
|
||||
for (ca = main->camera.first; ca; ca = ca->id.next) {
|
||||
ca->gpu_dof.fstop = 128.0f;
|
||||
ca->gpu_dof.focal_length = 1.0f;
|
||||
ca->gpu_dof.focus_distance = 1.0f;
|
||||
ca->gpu_dof.sensor = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(main, 273, 7)) {
|
||||
|
@@ -2682,6 +2682,11 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
|
||||
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next)
|
||||
writestruct(wd, DATA, "BGpic", 1, bgpic);
|
||||
if (v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd);
|
||||
|
||||
if (v3d->fx_settings.ssao)
|
||||
writestruct(wd, DATA, "GPUSSAOSettings", 1, v3d->fx_settings.ssao);
|
||||
if (v3d->fx_settings.dof)
|
||||
writestruct(wd, DATA, "GPUDOFSettings", 1, v3d->fx_settings.dof);
|
||||
}
|
||||
else if (sl->spacetype==SPACE_IPO) {
|
||||
SpaceIpo *sipo= (SpaceIpo *)sl;
|
||||
|
@@ -61,6 +61,10 @@ struct rcti;
|
||||
struct wmOperator;
|
||||
struct wmOperatorType;
|
||||
struct wmWindow;
|
||||
struct GPUFX;
|
||||
struct GPUOffScreen;
|
||||
struct GPUFXSettings;
|
||||
enum eGPUFXFlags;
|
||||
|
||||
/* for derivedmesh drawing callbacks, for view3d_select, .... */
|
||||
typedef struct ViewContext {
|
||||
@@ -303,8 +307,11 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active);
|
||||
|
||||
bool ED_view3d_context_activate(struct bContext *C);
|
||||
void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d);
|
||||
void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
|
||||
int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky);
|
||||
void ED_view3d_draw_offscreen(
|
||||
struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
|
||||
float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp,
|
||||
struct GPUOffScreen *ofs,
|
||||
struct GPUFX *fx, struct GPUFXSettings *fx_settings);
|
||||
|
||||
struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag,
|
||||
bool draw_background, int alpha_mode, char err_out[256]);
|
||||
|
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_camera_types.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_color_blend.h"
|
||||
#include "BLI_blenlib.h"
|
||||
@@ -42,6 +43,7 @@
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
@@ -68,6 +70,7 @@
|
||||
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_glew.h"
|
||||
#include "GPU_compositing.h"
|
||||
|
||||
|
||||
#include "render_intern.h"
|
||||
@@ -92,6 +95,7 @@ typedef struct OGLRender {
|
||||
ImageUser iuser;
|
||||
|
||||
GPUOffScreen *ofs;
|
||||
GPUFX *fx;
|
||||
int sizex, sizey;
|
||||
int write_still;
|
||||
|
||||
@@ -180,7 +184,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
int i;
|
||||
unsigned char *gp_rect;
|
||||
|
||||
GPU_offscreen_bind(oglrender->ofs);
|
||||
GPU_offscreen_bind(oglrender->ofs, true);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
@@ -200,22 +204,27 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
rgba_uchar_to_float(col_src, &gp_rect[i]);
|
||||
blend_color_mix_float(&rr->rectf[i], &rr->rectf[i], col_src);
|
||||
}
|
||||
GPU_offscreen_unbind(oglrender->ofs);
|
||||
GPU_offscreen_unbind(oglrender->ofs, true);
|
||||
|
||||
MEM_freeN(gp_rect);
|
||||
}
|
||||
}
|
||||
else if (view_context) {
|
||||
bool is_persp;
|
||||
/* full copy */
|
||||
GPUFXSettings fx_settings = v3d->fx_settings;
|
||||
|
||||
ED_view3d_draw_offscreen_init(scene, v3d);
|
||||
|
||||
GPU_offscreen_bind(oglrender->ofs); /* bind */
|
||||
GPU_offscreen_bind(oglrender->ofs, true); /* bind */
|
||||
|
||||
/* render 3d view */
|
||||
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
|
||||
/*int is_ortho = scene->r.mode & R_ORTHO;*/
|
||||
camera = v3d->camera;
|
||||
RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat);
|
||||
|
||||
is_persp = true;
|
||||
BKE_camera_to_gpu_dof(camera, &fx_settings);
|
||||
}
|
||||
else {
|
||||
rctf viewplane;
|
||||
@@ -224,12 +233,17 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
bool is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
|
||||
if (is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
|
||||
else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
|
||||
|
||||
is_persp = !is_ortho;
|
||||
}
|
||||
|
||||
rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
|
||||
|
||||
if ((scene->r.mode & R_OSA) == 0) {
|
||||
ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky);
|
||||
ED_view3d_draw_offscreen(
|
||||
scene, v3d, ar, sizex, sizey, NULL, winmat,
|
||||
draw_bgpic, draw_sky, is_persp,
|
||||
oglrender->ofs, oglrender->fx, &fx_settings);
|
||||
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
|
||||
}
|
||||
else {
|
||||
@@ -242,7 +256,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
BLI_jitter_init(jit_ofs, scene->r.osa);
|
||||
|
||||
/* first sample buffer, also initializes 'rv3d->persmat' */
|
||||
ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky);
|
||||
ED_view3d_draw_offscreen(
|
||||
scene, v3d, ar, sizex, sizey, NULL, winmat,
|
||||
draw_bgpic, draw_sky, is_persp,
|
||||
oglrender->ofs, oglrender->fx, &fx_settings);
|
||||
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
|
||||
|
||||
for (i = 0; i < sizex * sizey * 4; i++)
|
||||
@@ -255,7 +272,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
(jit_ofs[j][0] * 2.0f) / sizex,
|
||||
(jit_ofs[j][1] * 2.0f) / sizey);
|
||||
|
||||
ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_bgpic, draw_sky);
|
||||
ED_view3d_draw_offscreen(
|
||||
scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
|
||||
draw_bgpic, draw_sky, is_persp,
|
||||
oglrender->ofs, oglrender->fx, &fx_settings);
|
||||
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
|
||||
|
||||
for (i = 0; i < sizex * sizey * 4; i++)
|
||||
@@ -268,7 +288,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
MEM_freeN(accum_buffer);
|
||||
}
|
||||
|
||||
GPU_offscreen_unbind(oglrender->ofs); /* unbind */
|
||||
GPU_offscreen_unbind(oglrender->ofs, true); /* unbind */
|
||||
}
|
||||
else {
|
||||
/* shouldnt suddenly give errors mid-render but possible */
|
||||
@@ -448,6 +468,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
||||
* running notifiers again will overwrite */
|
||||
oglrender->scene->customdata_mask |= oglrender->scene->customdata_mask_modal;
|
||||
|
||||
if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO)) {
|
||||
oglrender->fx = GPU_fx_compositor_create();
|
||||
}
|
||||
}
|
||||
|
||||
/* create render */
|
||||
@@ -497,6 +520,9 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
|
||||
|
||||
if (oglrender->fx)
|
||||
GPU_fx_compositor_destroy(oglrender->fx);
|
||||
|
||||
GPU_offscreen_free(oglrender->ofs);
|
||||
|
||||
oglrender->scene->customdata_mask_modal = 0;
|
||||
|
@@ -7392,7 +7392,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
|
||||
if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) {
|
||||
if (ob->type == OB_MESH) {
|
||||
if (dt < OB_SOLID) {
|
||||
zbufoff = 1;
|
||||
zbufoff = true;
|
||||
dt = OB_SOLID;
|
||||
}
|
||||
|
||||
|
@@ -56,6 +56,7 @@
|
||||
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_material.h"
|
||||
#include "GPU_compositing.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
@@ -418,6 +419,11 @@ static void view3d_free(SpaceLink *sl)
|
||||
BKE_previewimg_free(&vd->defmaterial->preview);
|
||||
MEM_freeN(vd->defmaterial);
|
||||
}
|
||||
|
||||
if (vd->fx_settings.ssao)
|
||||
MEM_freeN(vd->fx_settings.ssao);
|
||||
if (vd->fx_settings.dof)
|
||||
MEM_freeN(vd->fx_settings.dof);
|
||||
}
|
||||
|
||||
|
||||
@@ -459,7 +465,11 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
|
||||
}
|
||||
|
||||
v3dn->properties_storage = NULL;
|
||||
|
||||
if (v3dn->fx_settings.dof)
|
||||
v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
|
||||
if (v3dn->fx_settings.ssao)
|
||||
v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao);
|
||||
|
||||
return (SpaceLink *)v3dn;
|
||||
}
|
||||
|
||||
@@ -559,6 +569,11 @@ static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar)
|
||||
GPU_offscreen_free(rv3d->gpuoffscreen);
|
||||
rv3d->gpuoffscreen = NULL;
|
||||
}
|
||||
|
||||
if (rv3d->compositor) {
|
||||
GPU_fx_compositor_destroy(rv3d->compositor);
|
||||
rv3d->compositor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
|
||||
@@ -713,6 +728,9 @@ static void view3d_main_area_free(ARegion *ar)
|
||||
if (rv3d->gpuoffscreen) {
|
||||
GPU_offscreen_free(rv3d->gpuoffscreen);
|
||||
}
|
||||
if (rv3d->compositor) {
|
||||
GPU_fx_compositor_destroy(rv3d->compositor);
|
||||
}
|
||||
|
||||
MEM_freeN(rv3d);
|
||||
ar->regiondata = NULL;
|
||||
@@ -736,6 +754,7 @@ static void *view3d_main_area_duplicate(void *poin)
|
||||
new->render_engine = NULL;
|
||||
new->sms = NULL;
|
||||
new->smooth_timer = NULL;
|
||||
new->compositor = NULL;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
@@ -94,6 +94,7 @@
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_material.h"
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_compositing.h"
|
||||
|
||||
#include "view3d_intern.h" /* own include */
|
||||
|
||||
@@ -1374,7 +1375,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
|
||||
}
|
||||
|
||||
if (rv3d->gpuoffscreen)
|
||||
GPU_offscreen_bind(rv3d->gpuoffscreen);
|
||||
GPU_offscreen_bind(rv3d->gpuoffscreen, true);
|
||||
else
|
||||
glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
|
||||
|
||||
@@ -1397,7 +1398,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
|
||||
draw_object_backbufsel(scene, v3d, rv3d, base->object);
|
||||
|
||||
if (rv3d->gpuoffscreen)
|
||||
GPU_offscreen_unbind(rv3d->gpuoffscreen);
|
||||
GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
|
||||
else
|
||||
ar->swap = 0; /* mark invalid backbuf for wm draw */
|
||||
|
||||
@@ -1423,10 +1424,10 @@ void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int form
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
|
||||
if (rv3d->gpuoffscreen) {
|
||||
GPU_offscreen_bind(rv3d->gpuoffscreen);
|
||||
GPU_offscreen_bind(rv3d->gpuoffscreen, true);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
glReadPixels(x, y, w, h, format, type, data);
|
||||
GPU_offscreen_unbind(rv3d->gpuoffscreen);
|
||||
GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
|
||||
}
|
||||
else {
|
||||
glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
|
||||
@@ -2532,7 +2533,10 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
|
||||
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
|
||||
|
||||
/* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */
|
||||
ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, false, false);
|
||||
ED_view3d_draw_offscreen(
|
||||
scene, v3d, &ar, winsize, winsize, viewmat, winmat,
|
||||
false, false, true,
|
||||
NULL, NULL, NULL);
|
||||
GPU_lamp_shadow_buffer_unbind(shadow->lamp);
|
||||
|
||||
v3d->drawtype = drawtype;
|
||||
@@ -3049,13 +3053,18 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool
|
||||
/* ED_view3d_draw_offscreen_init should be called before this to initialize
|
||||
* stuff like shadow buffers
|
||||
*/
|
||||
void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
|
||||
float viewmat[4][4], float winmat[4][4],
|
||||
bool do_bgpic, bool do_sky)
|
||||
void ED_view3d_draw_offscreen(
|
||||
Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
|
||||
float viewmat[4][4], float winmat[4][4],
|
||||
bool do_bgpic, bool do_sky, bool is_persp,
|
||||
GPUOffScreen *ofs,
|
||||
GPUFX *fx, GPUFXSettings *fx_settings)
|
||||
{
|
||||
struct bThemeState theme_state;
|
||||
int bwinx, bwiny;
|
||||
rcti brect;
|
||||
bool do_compositing = false;
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
@@ -3082,9 +3091,15 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
|
||||
* warning! can be slow so only free animated images - campbell */
|
||||
GPU_free_images_anim();
|
||||
}
|
||||
/* setup view matrices */
|
||||
|
||||
/* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
|
||||
view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
|
||||
|
||||
|
||||
/* framebuffer fx needed, we need to draw offscreen first */
|
||||
if (v3d->fx_settings.fx_flag && fx) {
|
||||
do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
|
||||
}
|
||||
|
||||
/* clear opengl buffers */
|
||||
if (do_sky) {
|
||||
view3d_main_area_clear(scene, v3d, ar, true);
|
||||
@@ -3097,6 +3112,13 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
|
||||
/* main drawing call */
|
||||
view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true);
|
||||
|
||||
/* post process */
|
||||
if (do_compositing) {
|
||||
if (!winmat)
|
||||
is_persp = rv3d->is_persp;
|
||||
GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
|
||||
}
|
||||
|
||||
if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
|
||||
/* draw grease-pencil stuff */
|
||||
ED_region_pixelspace(ar);
|
||||
@@ -3131,7 +3153,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
|
||||
ImBuf *ibuf;
|
||||
GPUOffScreen *ofs;
|
||||
bool draw_sky = (alpha_mode == R_ADDSKY);
|
||||
|
||||
|
||||
/* state changes make normal drawing go weird otherwise */
|
||||
glPushAttrib(GL_LIGHTING_BIT);
|
||||
|
||||
@@ -3144,11 +3166,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
|
||||
|
||||
ED_view3d_draw_offscreen_init(scene, v3d);
|
||||
|
||||
GPU_offscreen_bind(ofs);
|
||||
GPU_offscreen_bind(ofs, true);
|
||||
|
||||
/* render 3d view */
|
||||
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
|
||||
CameraParams params;
|
||||
GPUFXSettings fx_settings = {0};
|
||||
Object *camera = v3d->camera;
|
||||
|
||||
BKE_camera_params_init(¶ms);
|
||||
/* fallback for non camera objects */
|
||||
@@ -3158,10 +3182,18 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
|
||||
BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp);
|
||||
BKE_camera_params_compute_matrix(¶ms);
|
||||
|
||||
ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, draw_sky);
|
||||
BKE_camera_to_gpu_dof(camera, &fx_settings);
|
||||
|
||||
ED_view3d_draw_offscreen(
|
||||
scene, v3d, ar, sizex, sizey, NULL, params.winmat,
|
||||
draw_background, draw_sky, !params.is_ortho,
|
||||
ofs, NULL, &fx_settings);
|
||||
}
|
||||
else {
|
||||
ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, draw_sky);
|
||||
ED_view3d_draw_offscreen(
|
||||
scene, v3d, ar, sizex, sizey, NULL, NULL,
|
||||
draw_background, draw_sky, true,
|
||||
ofs, NULL, NULL);
|
||||
}
|
||||
|
||||
/* read in pixels & stamp */
|
||||
@@ -3173,7 +3205,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
|
||||
GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
|
||||
|
||||
/* unbind */
|
||||
GPU_offscreen_unbind(ofs);
|
||||
GPU_offscreen_unbind(ofs, true);
|
||||
GPU_offscreen_free(ofs);
|
||||
|
||||
glPopAttrib();
|
||||
@@ -3451,13 +3483,15 @@ static void update_lods(Scene *scene, float camera_pos[3])
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
|
||||
ARegion *ar, const char **grid_unit)
|
||||
{
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
unsigned int lay_used = v3d->lay_used;
|
||||
|
||||
|
||||
/* post processing */
|
||||
bool do_compositing = false;
|
||||
|
||||
/* shadow buffers, before we setup matrices */
|
||||
if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
|
||||
gpu_update_lamps_shadows(scene, v3d);
|
||||
@@ -3481,6 +3515,22 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
|
||||
}
|
||||
#endif
|
||||
|
||||
/* framebuffer fx needed, we need to draw offscreen first */
|
||||
if (v3d->fx_settings.fx_flag) {
|
||||
GPUFXSettings fx_settings;
|
||||
BKE_screen_gpu_fx_validate(&v3d->fx_settings);
|
||||
fx_settings = v3d->fx_settings;
|
||||
if (!rv3d->compositor)
|
||||
rv3d->compositor = GPU_fx_compositor_create();
|
||||
|
||||
if (rv3d->persp == RV3D_CAMOB && v3d->camera)
|
||||
BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
|
||||
else {
|
||||
fx_settings.dof = NULL;
|
||||
}
|
||||
do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
|
||||
}
|
||||
|
||||
/* clear the background */
|
||||
view3d_main_area_clear(scene, v3d, ar, false);
|
||||
|
||||
@@ -3492,6 +3542,11 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
|
||||
/* main drawing call */
|
||||
view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false);
|
||||
|
||||
/* post process */
|
||||
if (do_compositing) {
|
||||
GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
|
||||
}
|
||||
|
||||
/* Disable back anti-aliasing */
|
||||
if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
|
||||
glDisable(GL_MULTISAMPLE_ARB);
|
||||
|
@@ -54,6 +54,21 @@ set(SRC
|
||||
intern/gpu_material.c
|
||||
intern/gpu_simple_shader.c
|
||||
intern/gpu_select.c
|
||||
intern/gpu_compositing.c
|
||||
|
||||
shaders/gpu_shader_fx_lib.glsl
|
||||
shaders/gpu_shader_fx_ssao_frag.glsl
|
||||
shaders/gpu_shader_fx_dof_frag.glsl
|
||||
shaders/gpu_shader_fx_dof_vert.glsl
|
||||
shaders/gpu_shader_fx_vert.glsl
|
||||
shaders/gpu_shader_material.glsl
|
||||
shaders/gpu_shader_sep_gaussian_blur_frag.glsl
|
||||
shaders/gpu_shader_sep_gaussian_blur_vert.glsl
|
||||
shaders/gpu_shader_simple_frag.glsl
|
||||
shaders/gpu_shader_simple_vert.glsl
|
||||
shaders/gpu_shader_vertex.glsl
|
||||
shaders/gpu_shader_vsm_store_frag.glsl
|
||||
shaders/gpu_shader_vsm_store_vert.glsl
|
||||
|
||||
GPU_buffers.h
|
||||
GPU_draw.h
|
||||
@@ -63,6 +78,7 @@ set(SRC
|
||||
GPU_material.h
|
||||
GPU_simple_shader.h
|
||||
GPU_select.h
|
||||
GPU_compositing.h
|
||||
intern/gpu_codegen.h
|
||||
intern/gpu_extensions_private.h
|
||||
)
|
||||
@@ -76,6 +92,11 @@ data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_fx_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC)
|
||||
|
||||
if(WITH_GAMEENGINE)
|
||||
add_definitions(-DWITH_GAMEENGINE)
|
||||
|
88
source/blender/gpu/GPU_compositing.h
Normal file
88
source/blender/gpu/GPU_compositing.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2005 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Antony Riakiotakis.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file GPU_compositing.h
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#ifndef __GPU_COMPOSITING_H__
|
||||
#define __GPU_COMPOSITING_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* opaque handle for framebuffer compositing effects (defined in gpu_compositing.c )*/
|
||||
typedef struct GPUFX GPUFX;
|
||||
struct GPUDOFSettings;
|
||||
struct GPUSSAOSettings;
|
||||
struct GPUOffScreen;
|
||||
struct GPUFXSettings;
|
||||
struct RegionView3D;
|
||||
struct rcti;
|
||||
struct Scene;
|
||||
struct View3D;
|
||||
enum eGPUFXFlags;
|
||||
|
||||
/**** Public API *****/
|
||||
|
||||
typedef enum GPUFXShaderEffect {
|
||||
/* Screen space ambient occlusion shader */
|
||||
GPU_SHADER_FX_SSAO = 1,
|
||||
|
||||
/* depth of field passes. Yep, quite a complex effect */
|
||||
GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE = 2,
|
||||
GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO = 3,
|
||||
GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE = 4,
|
||||
GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR = 5,
|
||||
GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE = 6,
|
||||
} GPUFXShaderEffect;
|
||||
|
||||
/* keep in synch with enum above! */
|
||||
#define MAX_FX_SHADERS 11
|
||||
|
||||
/* generate a new FX compositor */
|
||||
GPUFX *GPU_fx_compositor_create(void);
|
||||
|
||||
/* destroy a text compositor */
|
||||
void GPU_fx_compositor_destroy(GPUFX *fx);
|
||||
|
||||
/* initialize a framebuffer with size taken from the viewport */
|
||||
bool GPU_fx_compositor_initialize_passes(
|
||||
GPUFX *fx, const struct rcti *rect, const struct rcti *scissor_rect,
|
||||
const struct GPUFXSettings *fx_settings);
|
||||
|
||||
/* do compositing on the fx passes that have been initialized */
|
||||
bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs);
|
||||
|
||||
void GPU_fx_compositor_init_dof_settings(struct GPUDOFSettings *dof);
|
||||
void GPU_fx_compositor_init_ssao_settings(struct GPUSSAOSettings *ssao);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __GPU_COMPOSITING_H__
|
@@ -107,11 +107,19 @@ int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
|
||||
* - if created with from_blender, will not free the texture
|
||||
*/
|
||||
|
||||
typedef enum GPUHDRType {
|
||||
GPU_HDR_NONE = 0,
|
||||
GPU_HDR_HALF_FLOAT = 1,
|
||||
GPU_HDR_FULL_FLOAT = (1 << 1),
|
||||
} GPUHDRType;
|
||||
|
||||
GPUTexture *GPU_texture_create_1D(int w, float *pixels, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels, GPUHDRType hdr, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels);
|
||||
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_2D_procedural(int w, int h, float *pixels, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_1D_procedural(int w, float *pixels, char err_out[256]);
|
||||
GPUTexture *GPU_texture_from_blender(struct Image *ima,
|
||||
struct ImageUser *iuser, bool is_data, double time, int mipmap);
|
||||
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
|
||||
@@ -126,6 +134,8 @@ void GPU_texture_ref(GPUTexture *tex);
|
||||
void GPU_texture_bind(GPUTexture *tex, int number);
|
||||
void GPU_texture_unbind(GPUTexture *tex);
|
||||
|
||||
void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter);
|
||||
|
||||
GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
|
||||
|
||||
int GPU_texture_target(GPUTexture *tex);
|
||||
@@ -145,11 +155,13 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex);
|
||||
GPUFrameBuffer *GPU_framebuffer_create(void);
|
||||
int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
|
||||
void GPU_framebuffer_texture_detach(GPUTexture *tex);
|
||||
void GPU_framebuffer_slot_bind(GPUFrameBuffer *fb, int slot);
|
||||
void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
|
||||
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
|
||||
void GPU_framebuffer_free(GPUFrameBuffer *fb);
|
||||
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
|
||||
|
||||
void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
|
||||
|
||||
void GPU_framebuffer_restore(void);
|
||||
void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex);
|
||||
|
||||
@@ -159,8 +171,8 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
|
||||
|
||||
GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]);
|
||||
void GPU_offscreen_free(GPUOffScreen *ofs);
|
||||
void GPU_offscreen_bind(GPUOffScreen *ofs);
|
||||
void GPU_offscreen_unbind(GPUOffScreen *ofs);
|
||||
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
|
||||
void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
|
||||
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
|
||||
int GPU_offscreen_width(GPUOffScreen *ofs);
|
||||
int GPU_offscreen_height(GPUOffScreen *ofs);
|
||||
@@ -177,7 +189,7 @@ void GPU_shader_unbind(void);
|
||||
|
||||
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
|
||||
void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
|
||||
int arraysize, float *value);
|
||||
int arraysize, const float *value);
|
||||
void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
|
||||
void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
|
||||
|
||||
@@ -190,6 +202,8 @@ typedef enum GPUBuiltinShader {
|
||||
} GPUBuiltinShader;
|
||||
|
||||
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
|
||||
GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
|
||||
|
||||
void GPU_shader_free_builtin_shaders(void);
|
||||
|
||||
/* Vertex attributes for shaders */
|
||||
|
@@ -65,6 +65,11 @@ import os
|
||||
sources.extend((
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"),
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"),
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"),
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_frag.glsl.c"),
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_vert.glsl.c"),
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_lib.glsl.c"),
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_vert.glsl.c"),
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"),
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"),
|
||||
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"),
|
||||
|
@@ -972,7 +972,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
|
||||
input->textype = type;
|
||||
|
||||
//input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
|
||||
input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
|
||||
input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
|
||||
input->textarget = GL_TEXTURE_2D;
|
||||
|
||||
MEM_freeN(link->ptr1);
|
||||
|
863
source/blender/gpu/intern/gpu_compositing.c
Normal file
863
source/blender/gpu/intern/gpu_compositing.c
Normal file
@@ -0,0 +1,863 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2006 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Antony Riakiotakis.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/gpu/intern/gpu_compositing.c
|
||||
* \ingroup gpu
|
||||
*
|
||||
* System that manages framebuffer compositing.
|
||||
*/
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_linklist.h"
|
||||
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "DNA_vec_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_gpu_types.h"
|
||||
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_compositing.h"
|
||||
|
||||
#include "GL/glew.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
static const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
|
||||
static const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
|
||||
|
||||
struct GPUFX {
|
||||
/* we borrow the term gbuffer from deferred rendering however this is just a regular
|
||||
* depth/color framebuffer. Could be extended later though */
|
||||
GPUFrameBuffer *gbuffer;
|
||||
|
||||
/* texture bound to the first color attachment of the gbuffer */
|
||||
GPUTexture *color_buffer;
|
||||
|
||||
/* second texture used for ping-pong compositing */
|
||||
GPUTexture *color_buffer_sec;
|
||||
|
||||
/* all those buffers below have to coexist. Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */
|
||||
int dof_downsampled_w;
|
||||
int dof_downsampled_h;
|
||||
|
||||
/* texture used for near coc and color blurring calculation */
|
||||
GPUTexture *dof_near_coc_buffer;
|
||||
/* blurred near coc buffer. */
|
||||
GPUTexture *dof_near_coc_blurred_buffer;
|
||||
/* final near coc buffer. */
|
||||
GPUTexture *dof_near_coc_final_buffer;
|
||||
|
||||
/* half size blur buffer */
|
||||
GPUTexture *dof_half_downsampled;
|
||||
/* high quality dof texture downsamplers. 6 levels means 64 pixels wide */
|
||||
GPUTexture *dof_nearfar_coc[6];
|
||||
GPUTexture *dof_near_blur;
|
||||
GPUTexture *dof_far_blur;
|
||||
GPUTexture *dof_concentric_samples_tex;
|
||||
|
||||
/* texture bound to the depth attachment of the gbuffer */
|
||||
GPUTexture *depth_buffer;
|
||||
|
||||
/* texture used for jittering for various effects */
|
||||
GPUTexture *jitter_buffer;
|
||||
|
||||
/* texture used for ssao */
|
||||
int ssao_sample_count;
|
||||
GPUTexture *ssao_concentric_samples_tex;
|
||||
|
||||
/* dimensions of the gbuffer */
|
||||
int gbuffer_dim[2];
|
||||
|
||||
GPUFXSettings settings;
|
||||
|
||||
/* or-ed flags of enabled effects */
|
||||
int effects;
|
||||
|
||||
/* number of passes, needed to detect if ping pong buffer allocation is needed */
|
||||
int num_passes;
|
||||
|
||||
/* we have a stencil, restore the previous state */
|
||||
bool restore_stencil;
|
||||
};
|
||||
|
||||
/* concentric mapping, see "A Low Distortion Map Between Disk and Square" and
|
||||
* http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */
|
||||
static GPUTexture * create_concentric_sample_texture(int side)
|
||||
{
|
||||
GPUTexture *tex;
|
||||
float midpoint = 0.5f * (side - 1);
|
||||
float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex");
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < side; i++) {
|
||||
for (j = 0; j < side; j++) {
|
||||
int index = (i * side + j) * 2;
|
||||
float a = 1.0f - i / midpoint;
|
||||
float b = 1.0f - j / midpoint;
|
||||
float phi, r;
|
||||
if (a * a > b * b) {
|
||||
r = a;
|
||||
phi = (M_PI_4) * (b / a);
|
||||
}
|
||||
else {
|
||||
r = b;
|
||||
phi = M_PI_2 - (M_PI_4) * (a / b);
|
||||
}
|
||||
texels[index] = r * cos(phi);
|
||||
texels[index + 1] = r * sin(phi);
|
||||
}
|
||||
}
|
||||
|
||||
tex = GPU_texture_create_1D_procedural(side * side, texels, NULL);
|
||||
MEM_freeN(texels);
|
||||
return tex;
|
||||
}
|
||||
|
||||
/* generate a new FX compositor */
|
||||
GPUFX *GPU_fx_compositor_create(void)
|
||||
{
|
||||
GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
|
||||
|
||||
return fx;
|
||||
}
|
||||
|
||||
static void cleanup_fx_dof_buffers(GPUFX *fx)
|
||||
{
|
||||
if (fx->dof_near_coc_blurred_buffer) {
|
||||
GPU_texture_free(fx->dof_near_coc_blurred_buffer);
|
||||
fx->dof_near_coc_blurred_buffer = NULL;
|
||||
}
|
||||
if (fx->dof_near_coc_buffer) {
|
||||
GPU_texture_free(fx->dof_near_coc_buffer);
|
||||
fx->dof_near_coc_buffer = NULL;
|
||||
}
|
||||
if (fx->dof_near_coc_final_buffer) {
|
||||
GPU_texture_free(fx->dof_near_coc_final_buffer);
|
||||
fx->dof_near_coc_final_buffer = NULL;
|
||||
}
|
||||
|
||||
if (fx->dof_half_downsampled) {
|
||||
GPU_texture_free(fx->dof_half_downsampled);
|
||||
fx->dof_half_downsampled = NULL;
|
||||
}
|
||||
if (fx->dof_nearfar_coc[0]) {
|
||||
int i;
|
||||
for (i = 0; i < 6; i++) {
|
||||
GPU_texture_free(fx->dof_nearfar_coc[i]);
|
||||
fx->dof_nearfar_coc[i] = NULL;
|
||||
}
|
||||
}
|
||||
if (fx->dof_near_blur) {
|
||||
GPU_texture_free(fx->dof_near_blur);
|
||||
fx->dof_near_blur = NULL;
|
||||
}
|
||||
if (fx->dof_far_blur) {
|
||||
GPU_texture_free(fx->dof_far_blur);
|
||||
fx->dof_far_blur = NULL;
|
||||
}
|
||||
if (fx->dof_concentric_samples_tex) {
|
||||
GPU_texture_free(fx->dof_concentric_samples_tex);
|
||||
fx->dof_concentric_samples_tex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
|
||||
{
|
||||
if (fx->color_buffer) {
|
||||
GPU_framebuffer_texture_detach(fx->color_buffer);
|
||||
GPU_texture_free(fx->color_buffer);
|
||||
fx->color_buffer = NULL;
|
||||
}
|
||||
|
||||
if (fx->color_buffer_sec) {
|
||||
GPU_framebuffer_texture_detach(fx->color_buffer_sec);
|
||||
GPU_texture_free(fx->color_buffer_sec);
|
||||
fx->color_buffer_sec = NULL;
|
||||
}
|
||||
|
||||
if (fx->depth_buffer) {
|
||||
GPU_framebuffer_texture_detach(fx->depth_buffer);
|
||||
GPU_texture_free(fx->depth_buffer);
|
||||
fx->depth_buffer = NULL;
|
||||
}
|
||||
|
||||
cleanup_fx_dof_buffers(fx);
|
||||
|
||||
if (fx->ssao_concentric_samples_tex) {
|
||||
GPU_texture_free(fx->ssao_concentric_samples_tex);
|
||||
fx->ssao_concentric_samples_tex = NULL;
|
||||
}
|
||||
|
||||
if (fx->jitter_buffer && do_fbo) {
|
||||
GPU_texture_free(fx->jitter_buffer);
|
||||
fx->jitter_buffer = NULL;
|
||||
}
|
||||
|
||||
if (fx->gbuffer && do_fbo) {
|
||||
GPU_framebuffer_free(fx->gbuffer);
|
||||
fx->gbuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* destroy a text compositor */
|
||||
void GPU_fx_compositor_destroy(GPUFX *fx)
|
||||
{
|
||||
cleanup_fx_gl_data(fx, true);
|
||||
MEM_freeN(fx);
|
||||
}
|
||||
|
||||
static GPUTexture * create_jitter_texture(void)
|
||||
{
|
||||
float jitter [64 * 64][2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 64 * 64; i++) {
|
||||
jitter[i][0] = 2.0f * BLI_frand() - 1.0;
|
||||
jitter[i][1] = 2.0f * BLI_frand() - 1.0;
|
||||
normalize_v2(jitter[i]);
|
||||
}
|
||||
|
||||
return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], NULL);
|
||||
}
|
||||
|
||||
|
||||
bool GPU_fx_compositor_initialize_passes(
|
||||
GPUFX *fx, const rcti *rect, const rcti *scissor_rect,
|
||||
const GPUFXSettings *fx_settings)
|
||||
{
|
||||
int w = BLI_rcti_size_x(rect) + 1, h = BLI_rcti_size_y(rect) + 1;
|
||||
char err_out[256];
|
||||
int num_passes = 0;
|
||||
char fx_flag = fx_settings->fx_flag;
|
||||
|
||||
fx->effects = 0;
|
||||
|
||||
if (!fx_settings) {
|
||||
cleanup_fx_gl_data(fx, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* disable effects if no options passed for them */
|
||||
if (!fx_settings->dof) {
|
||||
fx_flag &= ~GPU_FX_FLAG_DOF;
|
||||
}
|
||||
if (!fx_settings->ssao || fx_settings->ssao->samples < 1) {
|
||||
fx_flag &= ~GPU_FX_FLAG_SSAO;
|
||||
}
|
||||
|
||||
if (!fx_flag) {
|
||||
cleanup_fx_gl_data(fx, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
fx->num_passes = 0;
|
||||
/* dof really needs a ping-pong buffer to work */
|
||||
if (fx_flag & GPU_FX_FLAG_DOF)
|
||||
num_passes++;
|
||||
|
||||
if (fx_flag & GPU_FX_FLAG_SSAO)
|
||||
num_passes++;
|
||||
|
||||
if (!fx->gbuffer)
|
||||
fx->gbuffer = GPU_framebuffer_create();
|
||||
|
||||
/* try creating the jitter texture */
|
||||
if (!fx->jitter_buffer)
|
||||
fx->jitter_buffer = create_jitter_texture();
|
||||
|
||||
if (!fx->gbuffer)
|
||||
return false;
|
||||
|
||||
/* check if color buffers need recreation */
|
||||
if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
|
||||
cleanup_fx_gl_data(fx, false);
|
||||
|
||||
if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
|
||||
printf(".256%s\n", err_out);
|
||||
cleanup_fx_gl_data(fx, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) {
|
||||
printf("%.256s\n", err_out);
|
||||
cleanup_fx_gl_data(fx, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fx_flag & GPU_FX_FLAG_SSAO) {
|
||||
if (fx_settings->ssao->samples != fx->ssao_sample_count || !fx->ssao_concentric_samples_tex) {
|
||||
if (fx_settings->ssao->samples < 1)
|
||||
fx_settings->ssao->samples = 1;
|
||||
|
||||
fx->ssao_sample_count = fx_settings->ssao->samples;
|
||||
|
||||
if (fx->ssao_concentric_samples_tex) {
|
||||
GPU_texture_free(fx->ssao_concentric_samples_tex);
|
||||
}
|
||||
|
||||
fx->ssao_concentric_samples_tex = create_concentric_sample_texture(fx_settings->ssao->samples);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fx->ssao_concentric_samples_tex) {
|
||||
GPU_texture_free(fx->ssao_concentric_samples_tex);
|
||||
fx->ssao_concentric_samples_tex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* create textures for dof effect */
|
||||
if (fx_flag & GPU_FX_FLAG_DOF) {
|
||||
if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
|
||||
fx->dof_downsampled_w = w / 4;
|
||||
fx->dof_downsampled_h = h / 4;
|
||||
|
||||
if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
|
||||
fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
|
||||
{
|
||||
printf("%.256s\n", err_out);
|
||||
cleanup_fx_gl_data(fx, true);
|
||||
return false;
|
||||
}
|
||||
if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
|
||||
fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
|
||||
{
|
||||
printf("%.256s\n", err_out);
|
||||
cleanup_fx_gl_data(fx, true);
|
||||
return false;
|
||||
}
|
||||
if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
|
||||
fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
|
||||
{
|
||||
printf("%.256s\n", err_out);
|
||||
cleanup_fx_gl_data(fx, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* cleanup unnecessary buffers */
|
||||
cleanup_fx_dof_buffers(fx);
|
||||
}
|
||||
|
||||
/* we need to pass data between shader stages, allocate an extra color buffer */
|
||||
if (num_passes > 1) {
|
||||
if(!fx->color_buffer_sec) {
|
||||
if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
|
||||
printf(".256%s\n", err_out);
|
||||
cleanup_fx_gl_data(fx, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fx->color_buffer_sec) {
|
||||
GPU_framebuffer_texture_detach(fx->color_buffer_sec);
|
||||
GPU_texture_free(fx->color_buffer_sec);
|
||||
fx->color_buffer_sec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* bind the buffers */
|
||||
|
||||
/* first depth buffer, because system assumes read/write buffers */
|
||||
if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out))
|
||||
printf("%.256s\n", err_out);
|
||||
|
||||
if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out))
|
||||
printf("%.256s\n", err_out);
|
||||
|
||||
if(!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
|
||||
printf("%.256s\n", err_out);
|
||||
|
||||
GPU_texture_bind_as_framebuffer(fx->color_buffer);
|
||||
|
||||
/* enable scissor test. It's needed to ensure sculpting works correctly */
|
||||
if (scissor_rect) {
|
||||
int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
|
||||
int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
|
||||
glPushAttrib(GL_SCISSOR_BIT);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
|
||||
w_sc, h_sc);
|
||||
fx->restore_stencil = true;
|
||||
}
|
||||
else {
|
||||
fx->restore_stencil = false;
|
||||
}
|
||||
|
||||
fx->effects = fx_flag;
|
||||
|
||||
if (fx_settings)
|
||||
fx->settings = *fx_settings;
|
||||
fx->gbuffer_dim[0] = w;
|
||||
fx->gbuffer_dim[1] = h;
|
||||
|
||||
fx->num_passes = num_passes;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOffScreen *ofs, GPUTexture *target)
|
||||
{
|
||||
if ((*passes_left)-- == 1) {
|
||||
GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
|
||||
if (ofs) {
|
||||
GPU_offscreen_bind(ofs, false);
|
||||
}
|
||||
else
|
||||
GPU_framebuffer_restore();
|
||||
}
|
||||
else {
|
||||
/* bind the ping buffer to the color buffer */
|
||||
GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs)
|
||||
{
|
||||
GPUTexture *src, *target;
|
||||
int numslots = 0;
|
||||
float invproj[4][4];
|
||||
int i;
|
||||
/* number of passes left. when there are no more passes, the result is passed to the frambuffer */
|
||||
int passes_left = fx->num_passes;
|
||||
/* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
|
||||
float viewvecs[3][4] = {
|
||||
{-1.0f, -1.0f, -1.0f, 1.0f},
|
||||
{1.0f, -1.0f, -1.0f, 1.0f},
|
||||
{-1.0f, 1.0f, -1.0f, 1.0f}
|
||||
};
|
||||
|
||||
if (fx->effects == 0)
|
||||
return false;
|
||||
|
||||
/* first, unbind the render-to-texture framebuffer */
|
||||
GPU_framebuffer_texture_detach(fx->color_buffer);
|
||||
GPU_framebuffer_texture_detach(fx->depth_buffer);
|
||||
|
||||
if (fx->restore_stencil)
|
||||
glPopAttrib();
|
||||
|
||||
src = fx->color_buffer;
|
||||
target = fx->color_buffer_sec;
|
||||
|
||||
/* set up quad buffer */
|
||||
glVertexPointer(2, GL_FLOAT, 0, fullscreencos);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
/* full screen FX pass */
|
||||
|
||||
/* invert the view matrix */
|
||||
invert_m4_m4(invproj, projmat);
|
||||
|
||||
/* convert the view vectors to view space */
|
||||
for (i = 0; i < 3; i++) {
|
||||
mul_m4_v4(invproj, viewvecs[i]);
|
||||
/* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
|
||||
mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
|
||||
if (is_persp)
|
||||
mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
|
||||
viewvecs[i][3] = 1.0;
|
||||
}
|
||||
|
||||
/* we need to store the differences */
|
||||
viewvecs[1][0] -= viewvecs[0][0];
|
||||
viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
|
||||
|
||||
/* calculate a depth offset as well */
|
||||
if (!is_persp) {
|
||||
float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
|
||||
mul_m4_v4(invproj, vec_far);
|
||||
mul_v3_fl(vec_far, 1.0f / vec_far[3]);
|
||||
viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
|
||||
}
|
||||
|
||||
/* set invalid color in case shader fails */
|
||||
glColor3f(1.0, 0.0, 1.0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
/* ssao pass */
|
||||
if (fx->effects & GPU_FX_FLAG_SSAO) {
|
||||
GPUShader *ssao_shader;
|
||||
ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
|
||||
if (ssao_shader) {
|
||||
const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
|
||||
int color_uniform, depth_uniform;
|
||||
int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform;
|
||||
int ssao_jitter_uniform, ssao_concentric_tex;
|
||||
float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
|
||||
float sample_params[4];
|
||||
|
||||
sample_params[0] = fx->ssao_sample_count * fx->ssao_sample_count;
|
||||
/* multiplier so we tile the random texture on screen */
|
||||
sample_params[2] = fx->gbuffer_dim[0] / 64.0;
|
||||
sample_params[3] = fx->gbuffer_dim[1] / 64.0;
|
||||
|
||||
ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params");
|
||||
ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color");
|
||||
color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer");
|
||||
depth_uniform = GPU_shader_get_uniform(ssao_shader, "depthbuffer");
|
||||
viewvecs_uniform = GPU_shader_get_uniform(ssao_shader, "viewvecs");
|
||||
ssao_sample_params_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_sample_params");
|
||||
ssao_concentric_tex = GPU_shader_get_uniform(ssao_shader, "ssao_concentric_tex");
|
||||
ssao_jitter_uniform = GPU_shader_get_uniform(ssao_shader, "jitter_tex");
|
||||
|
||||
GPU_shader_bind(ssao_shader);
|
||||
|
||||
GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params);
|
||||
GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color);
|
||||
GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]);
|
||||
GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 4, 1, sample_params);
|
||||
|
||||
GPU_texture_bind(src, numslots++);
|
||||
GPU_shader_uniform_texture(ssao_shader, color_uniform, src);
|
||||
|
||||
GPU_texture_bind(fx->depth_buffer, numslots++);
|
||||
GPU_depth_texture_mode(fx->depth_buffer, false, true);
|
||||
GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer);
|
||||
|
||||
GPU_texture_bind(fx->jitter_buffer, numslots++);
|
||||
GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer);
|
||||
|
||||
GPU_texture_bind(fx->ssao_concentric_samples_tex, numslots++);
|
||||
GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_concentric_samples_tex);
|
||||
|
||||
/* draw */
|
||||
gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
/* disable bindings */
|
||||
GPU_texture_unbind(src);
|
||||
GPU_depth_texture_mode(fx->depth_buffer, true, false);
|
||||
GPU_texture_unbind(fx->depth_buffer);
|
||||
GPU_texture_unbind(fx->jitter_buffer);
|
||||
GPU_texture_unbind(fx->ssao_concentric_samples_tex);
|
||||
|
||||
/* may not be attached, in that case this just returns */
|
||||
if (target) {
|
||||
GPU_framebuffer_texture_detach(target);
|
||||
if (ofs) {
|
||||
GPU_offscreen_bind(ofs, false);
|
||||
}
|
||||
else {
|
||||
GPU_framebuffer_restore();
|
||||
}
|
||||
}
|
||||
|
||||
/* swap here, after src/target have been unbound */
|
||||
SWAP(GPUTexture *, target, src);
|
||||
numslots = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* second pass, dof */
|
||||
if (fx->effects & GPU_FX_FLAG_DOF) {
|
||||
const GPUDOFSettings *fx_dof = fx->settings.dof;
|
||||
GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
|
||||
float dof_params[4];
|
||||
float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
|
||||
float scale_camera = 0.001f / scale;
|
||||
float aperture = 2.0f * scale_camera * fx_dof->focal_length / fx_dof->fstop;
|
||||
|
||||
dof_params[0] = aperture * fabs(scale_camera * fx_dof->focal_length / (fx_dof->focus_distance - scale_camera * fx_dof->focal_length));
|
||||
dof_params[1] = fx_dof->focus_distance;
|
||||
dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
|
||||
dof_params[3] = 0.0f;
|
||||
|
||||
/* DOF effect has many passes but most of them are performed on a texture whose dimensions are 4 times less than the original
|
||||
* (16 times lower than original screen resolution). Technique used is not very exact but should be fast enough and is based
|
||||
* on "Practical Post-Process Depth of Field" see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
|
||||
dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
|
||||
dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
|
||||
dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
|
||||
dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
|
||||
dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);
|
||||
|
||||
/* error occured, restore framebuffers and return */
|
||||
if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
|
||||
GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
|
||||
GPU_framebuffer_restore();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* pass first, first level of blur in low res buffer */
|
||||
{
|
||||
int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
|
||||
int viewvecs_uniform;
|
||||
|
||||
float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
|
||||
|
||||
dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
|
||||
invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
|
||||
color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
|
||||
depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
|
||||
viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
|
||||
|
||||
GPU_shader_bind(dof_shader_pass1);
|
||||
|
||||
GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
|
||||
GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
|
||||
GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
|
||||
|
||||
GPU_texture_bind(src, numslots++);
|
||||
GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src);
|
||||
|
||||
GPU_texture_bind(fx->depth_buffer, numslots++);
|
||||
GPU_depth_texture_mode(fx->depth_buffer, false, true);
|
||||
GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
|
||||
|
||||
/* target is the downsampled coc buffer */
|
||||
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
|
||||
/* binding takes care of setting the viewport to the downsampled size */
|
||||
GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
/* disable bindings */
|
||||
GPU_texture_unbind(src);
|
||||
GPU_depth_texture_mode(fx->depth_buffer, true, false);
|
||||
GPU_texture_unbind(fx->depth_buffer);
|
||||
|
||||
GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
|
||||
numslots = 0;
|
||||
}
|
||||
|
||||
/* second pass, gaussian blur the downsampled image */
|
||||
{
|
||||
int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
|
||||
int viewvecs_uniform;
|
||||
float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
|
||||
1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
|
||||
float tmp = invrendertargetdim[0];
|
||||
invrendertargetdim[0] = 0.0f;
|
||||
|
||||
dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
|
||||
|
||||
dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
|
||||
invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim");
|
||||
color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
|
||||
depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer");
|
||||
viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs");
|
||||
|
||||
/* Blurring vertically */
|
||||
GPU_shader_bind(dof_shader_pass2);
|
||||
|
||||
GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
|
||||
GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
|
||||
GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]);
|
||||
|
||||
GPU_texture_bind(fx->depth_buffer, numslots++);
|
||||
GPU_depth_texture_mode(fx->depth_buffer, false, true);
|
||||
GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer);
|
||||
|
||||
GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
|
||||
GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer);
|
||||
|
||||
/* use final buffer as a temp here */
|
||||
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
|
||||
|
||||
/* Drawing quad */
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
/* *unbind/detach */
|
||||
GPU_texture_unbind(fx->dof_near_coc_buffer);
|
||||
GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
|
||||
|
||||
/* Blurring horizontally */
|
||||
invrendertargetdim[0] = tmp;
|
||||
invrendertargetdim[1] = 0.0f;
|
||||
GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
|
||||
|
||||
GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
|
||||
GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer);
|
||||
|
||||
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
/* *unbind/detach */
|
||||
GPU_depth_texture_mode(fx->depth_buffer, true, false);
|
||||
GPU_texture_unbind(fx->depth_buffer);
|
||||
|
||||
GPU_texture_unbind(fx->dof_near_coc_final_buffer);
|
||||
GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);
|
||||
|
||||
dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
|
||||
|
||||
numslots = 0;
|
||||
}
|
||||
|
||||
/* third pass, calculate near coc */
|
||||
{
|
||||
int near_coc_downsampled, near_coc_blurred;
|
||||
|
||||
near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
|
||||
near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer");
|
||||
|
||||
GPU_shader_bind(dof_shader_pass3);
|
||||
|
||||
GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
|
||||
GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer);
|
||||
|
||||
GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
|
||||
GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer);
|
||||
|
||||
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
/* disable bindings */
|
||||
GPU_texture_unbind(fx->dof_near_coc_buffer);
|
||||
GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
|
||||
|
||||
/* unbinding here restores the size to the original */
|
||||
GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
|
||||
|
||||
numslots = 0;
|
||||
}
|
||||
|
||||
/* fourth pass blur final coc once to eliminate discontinuities */
|
||||
{
|
||||
int near_coc_downsampled;
|
||||
int invrendertargetdim_uniform;
|
||||
float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
|
||||
1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
|
||||
|
||||
near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer");
|
||||
invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim");
|
||||
|
||||
GPU_shader_bind(dof_shader_pass4);
|
||||
|
||||
GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
|
||||
GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer);
|
||||
GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
|
||||
|
||||
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
/* disable bindings */
|
||||
GPU_texture_unbind(fx->dof_near_coc_final_buffer);
|
||||
|
||||
/* unbinding here restores the size to the original */
|
||||
GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
|
||||
GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
|
||||
|
||||
numslots = 0;
|
||||
}
|
||||
|
||||
/* final pass, merge blurred layers according to final calculated coc */
|
||||
{
|
||||
int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform;
|
||||
int invrendertargetdim_uniform, viewvecs_uniform;
|
||||
float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
|
||||
|
||||
medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer");
|
||||
high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer");
|
||||
dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params");
|
||||
invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim");
|
||||
original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer");
|
||||
depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer");
|
||||
viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs");
|
||||
|
||||
GPU_shader_bind(dof_shader_pass5);
|
||||
|
||||
GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params);
|
||||
GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
|
||||
GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]);
|
||||
|
||||
GPU_texture_bind(src, numslots++);
|
||||
GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src);
|
||||
|
||||
GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
|
||||
GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
|
||||
|
||||
GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
|
||||
GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer);
|
||||
|
||||
GPU_texture_bind(fx->depth_buffer, numslots++);
|
||||
GPU_depth_texture_mode(fx->depth_buffer, false, true);
|
||||
GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer);
|
||||
|
||||
/* if this is the last pass, prepare for rendering on the frambuffer */
|
||||
gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
/* disable bindings */
|
||||
GPU_texture_unbind(fx->dof_near_coc_buffer);
|
||||
GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
|
||||
GPU_texture_unbind(src);
|
||||
GPU_depth_texture_mode(fx->depth_buffer, true, false);
|
||||
GPU_texture_unbind(fx->depth_buffer);
|
||||
|
||||
/* may not be attached, in that case this just returns */
|
||||
if (target) {
|
||||
GPU_framebuffer_texture_detach(target);
|
||||
if (ofs) {
|
||||
GPU_offscreen_bind(ofs, false);
|
||||
}
|
||||
else {
|
||||
GPU_framebuffer_restore();
|
||||
}
|
||||
}
|
||||
|
||||
SWAP(GPUTexture *, target, src);
|
||||
numslots = 0;
|
||||
}
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
GPU_shader_unbind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
|
||||
{
|
||||
fx_dof->fstop = 128.0f;
|
||||
fx_dof->focal_length = 1.0f;
|
||||
fx_dof->focus_distance = 1.0f;
|
||||
fx_dof->sensor = 1.0f;
|
||||
}
|
||||
|
||||
void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
|
||||
{
|
||||
fx_ssao->factor = 1.0f;
|
||||
fx_ssao->distance_max = 0.2f;
|
||||
fx_ssao->attenuation = 1.0f;
|
||||
fx_ssao->samples = 4;
|
||||
}
|
@@ -47,6 +47,7 @@
|
||||
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_compositing.h"
|
||||
#include "GPU_simple_shader.h"
|
||||
|
||||
#include "intern/gpu_extensions_private.h"
|
||||
@@ -78,10 +79,17 @@ extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_fx_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_fx_lib_glsl[];
|
||||
|
||||
typedef struct GPUShaders {
|
||||
GPUShader *vsm_store;
|
||||
GPUShader *sep_gaussian_blur;
|
||||
/* cache for shader fx. Those can exist in combinations so store them here */
|
||||
GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
|
||||
} GPUShaders;
|
||||
|
||||
static struct GPUGlobal {
|
||||
@@ -364,7 +372,9 @@ static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, i
|
||||
MEM_freeN(pixels);
|
||||
}
|
||||
|
||||
static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth, char err_out[256])
|
||||
static GPUTexture *GPU_texture_create_nD(
|
||||
int w, int h, int n, float *fpixels, int depth, GPUHDRType hdr_type, int components,
|
||||
char err_out[256])
|
||||
{
|
||||
GPUTexture *tex;
|
||||
GLenum type, format, internalformat;
|
||||
@@ -411,12 +421,45 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
|
||||
internalformat = GL_DEPTH_COMPONENT;
|
||||
}
|
||||
else {
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
format = GL_RGBA;
|
||||
internalformat = GL_RGBA8;
|
||||
type = GL_FLOAT;
|
||||
|
||||
if (fpixels)
|
||||
if (components == 4) {
|
||||
format = GL_RGBA;
|
||||
switch (hdr_type) {
|
||||
case GPU_HDR_NONE:
|
||||
internalformat = GL_RGBA8;
|
||||
break;
|
||||
case GPU_HDR_HALF_FLOAT:
|
||||
internalformat = GL_RGBA16F;
|
||||
break;
|
||||
case GPU_HDR_FULL_FLOAT:
|
||||
internalformat = GL_RGBA32F;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (components == 2) {
|
||||
format = GL_RG;
|
||||
switch (hdr_type) {
|
||||
case GPU_HDR_NONE:
|
||||
internalformat = GL_RG8;
|
||||
break;
|
||||
case GPU_HDR_HALF_FLOAT:
|
||||
internalformat = GL_RG16F;
|
||||
break;
|
||||
case GPU_HDR_FULL_FLOAT:
|
||||
internalformat = GL_RG32F;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fpixels && hdr_type == GPU_HDR_NONE) {
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
pixels = GPU_texture_convert_pixels(w*h, fpixels);
|
||||
}
|
||||
}
|
||||
|
||||
if (tex->target == GL_TEXTURE_1D) {
|
||||
@@ -651,7 +694,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
|
||||
|
||||
GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
|
||||
{
|
||||
GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out);
|
||||
GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, err_out);
|
||||
|
||||
if (tex)
|
||||
GPU_texture_unbind(tex);
|
||||
@@ -659,9 +702,9 @@ GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
|
||||
return tex;
|
||||
}
|
||||
|
||||
GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256])
|
||||
GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, GPUHDRType hdr, char err_out[256])
|
||||
{
|
||||
GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, err_out);
|
||||
GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, err_out);
|
||||
|
||||
if (tex)
|
||||
GPU_texture_unbind(tex);
|
||||
@@ -671,7 +714,7 @@ GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256
|
||||
|
||||
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
|
||||
{
|
||||
GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, err_out);
|
||||
GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, err_out);
|
||||
|
||||
if (tex)
|
||||
GPU_texture_unbind(tex);
|
||||
@@ -684,13 +727,45 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
|
||||
*/
|
||||
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
|
||||
{
|
||||
GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, err_out);
|
||||
GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, err_out);
|
||||
|
||||
if (tex) {
|
||||
/* Now we tweak some of the settings */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, size, size, 0, GL_RG, GL_FLOAT, NULL);
|
||||
|
||||
GPU_texture_unbind(tex);
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
GPUTexture *GPU_texture_create_2D_procedural(int w, int h, float *pixels, char err_out[256])
|
||||
{
|
||||
GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
|
||||
|
||||
if (tex) {
|
||||
/* Now we tweak some of the settings */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
GPU_texture_unbind(tex);
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
GPUTexture *GPU_texture_create_1D_procedural(int w, float *pixels, char err_out[256])
|
||||
{
|
||||
GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
|
||||
|
||||
if (tex) {
|
||||
/* Now we tweak some of the settings */
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
GPU_texture_unbind(tex);
|
||||
}
|
||||
@@ -702,7 +777,7 @@ void GPU_invalid_tex_init(void)
|
||||
{
|
||||
float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
|
||||
GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
|
||||
GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, NULL);
|
||||
GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
|
||||
GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
|
||||
}
|
||||
|
||||
@@ -792,6 +867,45 @@ void GPU_texture_unbind(GPUTexture *tex)
|
||||
GPU_print_error("Post Texture Unbind");
|
||||
}
|
||||
|
||||
void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter)
|
||||
{
|
||||
GLenum arbnumber;
|
||||
|
||||
if (tex->number >= GG.maxtextures) {
|
||||
GPU_print_error("Not enough texture slots.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tex->depth) {
|
||||
GPU_print_error("Not a depth texture.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tex->number == -1)
|
||||
return;
|
||||
|
||||
GPU_print_error("Pre Texture Unbind");
|
||||
|
||||
arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
|
||||
if (tex->number != 0) glActiveTextureARB(arbnumber);
|
||||
if (compare)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||
else
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
|
||||
if (use_filter) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
|
||||
GPU_print_error("Post Texture Unbind");
|
||||
}
|
||||
|
||||
void GPU_texture_free(GPUTexture *tex)
|
||||
{
|
||||
tex->refcount--;
|
||||
@@ -982,13 +1096,23 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
|
||||
glPushMatrix();
|
||||
}
|
||||
|
||||
void GPU_framebuffer_slot_bind(GPUFrameBuffer *fb, int slot)
|
||||
void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
|
||||
{
|
||||
int numslots = 0, i;
|
||||
GLenum attachments[4];
|
||||
|
||||
if (!fb->colortex[slot]) {
|
||||
fprintf(stderr, "Error, framebuffer slot empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0 ; i < 4; i++) {
|
||||
if (fb->colortex[i]) {
|
||||
attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
|
||||
numslots++;
|
||||
}
|
||||
}
|
||||
|
||||
/* push attributes */
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
@@ -997,7 +1121,7 @@ void GPU_framebuffer_slot_bind(GPUFrameBuffer *fb, int slot)
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
|
||||
|
||||
/* last bound prevails here, better allow explicit control here too */
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
|
||||
glDrawBuffers(numslots, attachments);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
|
||||
|
||||
/* push matrices and set default viewport and matrix */
|
||||
@@ -1023,6 +1147,18 @@ void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUS
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
|
||||
/* last bound prevails here, better allow explicit control here too */
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
|
||||
|
||||
/* push matrices and set default viewport and matrix */
|
||||
glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
|
||||
GG.currentfb = fb->object;
|
||||
GG.currentfb = fb->object;
|
||||
}
|
||||
|
||||
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
|
||||
{
|
||||
@@ -1045,7 +1181,6 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GPU_framebuffer_free(GPUFrameBuffer *fb)
|
||||
{
|
||||
int i;
|
||||
@@ -1080,8 +1215,8 @@ void GPU_framebuffer_restore(void)
|
||||
|
||||
void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
|
||||
{
|
||||
float scaleh[2] = {1.0f/GPU_texture_opengl_width(blurtex), 0.0f};
|
||||
float scalev[2] = {0.0f, 1.0f/GPU_texture_opengl_height(tex)};
|
||||
const float scaleh[2] = {1.0f / GPU_texture_opengl_width(blurtex), 0.0f};
|
||||
const float scalev[2] = {0.0f, 1.0f / GPU_texture_opengl_height(tex)};
|
||||
|
||||
GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
|
||||
int scale_uniform, texture_source_uniform;
|
||||
@@ -1103,7 +1238,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
|
||||
GG.currentfb = blurfb->object;
|
||||
|
||||
GPU_shader_bind(blur_shader);
|
||||
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scaleh);
|
||||
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
|
||||
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
|
||||
glViewport(0, 0, GPU_texture_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
|
||||
|
||||
@@ -1126,7 +1261,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
|
||||
glTexCoord2d(1, 1); glVertex2f(-1, -1);
|
||||
glTexCoord2d(0, 1); glVertex2f(1, -1);
|
||||
glEnd();
|
||||
|
||||
|
||||
/* Blurring vertically */
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
|
||||
@@ -1135,7 +1270,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
|
||||
GG.currentfb = fb->object;
|
||||
|
||||
glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
|
||||
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scalev);
|
||||
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
|
||||
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
|
||||
GPU_texture_bind(blurtex, 0);
|
||||
|
||||
@@ -1180,7 +1315,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ofs->color = GPU_texture_create_2D(width, height, NULL, err_out);
|
||||
ofs->color = GPU_texture_create_2D(width, height, NULL, GPU_HDR_NONE, err_out);
|
||||
if (!ofs->color) {
|
||||
GPU_offscreen_free(ofs);
|
||||
return NULL;
|
||||
@@ -1214,15 +1349,20 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
|
||||
MEM_freeN(ofs);
|
||||
}
|
||||
|
||||
void GPU_offscreen_bind(GPUOffScreen *ofs)
|
||||
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
|
||||
{
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
GPU_texture_bind_as_framebuffer(ofs->color);
|
||||
if (save)
|
||||
GPU_framebuffer_slots_bind(ofs->fb, 0);
|
||||
else {
|
||||
GPU_framebuffer_bind_no_save(ofs->fb, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_offscreen_unbind(GPUOffScreen *ofs)
|
||||
void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
|
||||
{
|
||||
GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
|
||||
if (restore)
|
||||
GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
|
||||
GPU_framebuffer_restore();
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
@@ -1250,6 +1390,7 @@ struct GPUShader {
|
||||
GLhandleARB fragment; /* handle for fragment shader */
|
||||
GLhandleARB lib; /* handle for libment shader */
|
||||
int totattrib; /* total number of attributes */
|
||||
int uniforms; /* required uniforms */
|
||||
};
|
||||
|
||||
static void shader_print_errors(const char *task, char *log, const char **code, int totcode)
|
||||
@@ -1494,7 +1635,7 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
|
||||
return glGetUniformLocationARB(shader->object, name);
|
||||
}
|
||||
|
||||
void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, float *value)
|
||||
void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
|
||||
{
|
||||
if (location == -1)
|
||||
return;
|
||||
@@ -1588,8 +1729,64 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define MAX_DEFINES 100
|
||||
|
||||
GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
|
||||
{
|
||||
int offset;
|
||||
char defines[MAX_DEFINES] = "";
|
||||
/* avoid shaders out of range */
|
||||
if (effects >= MAX_FX_SHADERS)
|
||||
return NULL;
|
||||
|
||||
offset = 2 * effects;
|
||||
|
||||
if (persp) {
|
||||
offset += 1;
|
||||
strcat(defines, "#define PERSP_MATRIX\n");
|
||||
}
|
||||
|
||||
if (!GG.shaders.fx_shaders[offset]) {
|
||||
switch(effects) {
|
||||
case GPU_SHADER_FX_SSAO:
|
||||
GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
|
||||
break;
|
||||
|
||||
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
|
||||
strcat(defines, "#define FIRST_PASS\n");
|
||||
GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
|
||||
break;
|
||||
|
||||
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
|
||||
strcat(defines, "#define SECOND_PASS\n");
|
||||
GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
|
||||
break;
|
||||
|
||||
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
|
||||
strcat(defines, "#define THIRD_PASS\n");
|
||||
GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
|
||||
break;
|
||||
|
||||
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
|
||||
strcat(defines, "#define FOURTH_PASS\n");
|
||||
GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
|
||||
break;
|
||||
|
||||
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
|
||||
strcat(defines, "#define FIFTH_PASS\n");
|
||||
GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return GG.shaders.fx_shaders[offset];
|
||||
}
|
||||
|
||||
|
||||
void GPU_shader_free_builtin_shaders(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (GG.shaders.vsm_store) {
|
||||
MEM_freeN(GG.shaders.vsm_store);
|
||||
GG.shaders.vsm_store = NULL;
|
||||
@@ -1599,6 +1796,13 @@ void GPU_shader_free_builtin_shaders(void)
|
||||
MEM_freeN(GG.shaders.sep_gaussian_blur);
|
||||
GG.shaders.sep_gaussian_blur = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
|
||||
if (GG.shaders.fx_shaders[i]) {
|
||||
MEM_freeN(GG.shaders.fx_shaders[i]);
|
||||
GG.shaders.fx_shaders[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
206
source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
Normal file
206
source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
Normal file
@@ -0,0 +1,206 @@
|
||||
/* amount of offset to move one pixel left-right.
|
||||
* In second pass some dimensions are zero to control verical/horizontal convolution */
|
||||
uniform vec2 invrendertargetdim;
|
||||
// color buffer
|
||||
uniform sampler2D colorbuffer;
|
||||
//blurred color buffer for DOF effect
|
||||
uniform sampler2D blurredcolorbuffer;
|
||||
// slightly blurred buffer
|
||||
uniform sampler2D mblurredcolorbuffer;
|
||||
// depth buffer
|
||||
uniform sampler2D depthbuffer;
|
||||
|
||||
// this includes focal distance in x and aperture size in y
|
||||
uniform vec4 dof_params;
|
||||
|
||||
// viewvectors for reconstruction of world space
|
||||
uniform vec4 viewvecs[3];
|
||||
|
||||
// coordinates on framebuffer in normalized (0.0-1.0) uv space
|
||||
varying vec4 uvcoordsvar;
|
||||
|
||||
/* color texture coordinates, offset by a small amount */
|
||||
varying vec2 color_uv1;
|
||||
varying vec2 color_uv2;
|
||||
|
||||
varying vec2 depth_uv1;
|
||||
varying vec2 depth_uv2;
|
||||
varying vec2 depth_uv3;
|
||||
varying vec2 depth_uv4;
|
||||
|
||||
|
||||
float calculate_far_coc(in float zdepth)
|
||||
{
|
||||
float coc = dof_params.x * max(1.0 - dof_params.y / zdepth, 0.0);
|
||||
|
||||
/* multiply by 1.0 / sensor size to get the normalized size */
|
||||
return coc * dof_params.z;
|
||||
}
|
||||
|
||||
/* near coc only! when distance is nearer than focus plane first term is bigger than one */
|
||||
vec4 calculate_near_coc(in vec4 zdepth)
|
||||
{
|
||||
vec4 coc = dof_params.x * max(vec4(dof_params.y) / zdepth - vec4(1.0), vec4(0.0));
|
||||
|
||||
/* multiply by 1.0 / sensor size to get the normalized size */
|
||||
return coc * dof_params.z;
|
||||
}
|
||||
|
||||
/* first pass blurs the color buffer heavily and gets the near coc only.
|
||||
* There are many texture accesses here but they are done on a
|
||||
* lower resolution image so overall bandwidth is not a concern */
|
||||
void first_pass()
|
||||
{
|
||||
vec4 depth;
|
||||
vec4 zdepth;
|
||||
vec4 coc;
|
||||
float final_coc;
|
||||
|
||||
/* amount to add to uvs so that they move one row further */
|
||||
vec2 offset_row[3];
|
||||
offset_row[0] = vec2(0.0, invrendertargetdim.y);
|
||||
offset_row[1] = 2.0 * offset_row[0];
|
||||
offset_row[2] = 3.0 * offset_row[0];
|
||||
|
||||
/* heavily blur the image */
|
||||
vec4 color = texture2D(colorbuffer, color_uv1);
|
||||
color += texture2D(colorbuffer, color_uv1 + offset_row[1]);
|
||||
color += texture2D(colorbuffer, color_uv2);
|
||||
color += texture2D(colorbuffer, color_uv2 + offset_row[1]);
|
||||
color /= 4.0;
|
||||
|
||||
depth.r = texture2D(depthbuffer, depth_uv1).r;
|
||||
depth.g = texture2D(depthbuffer, depth_uv2).r;
|
||||
depth.b = texture2D(depthbuffer, depth_uv3).r;
|
||||
depth.a = texture2D(depthbuffer, depth_uv4).r;
|
||||
|
||||
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
|
||||
coc = calculate_near_coc(zdepth);
|
||||
|
||||
depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[0]).r;
|
||||
depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[0]).r;
|
||||
depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[0]).r;
|
||||
depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[0]).r;
|
||||
|
||||
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
|
||||
coc = max(calculate_near_coc(zdepth), coc);
|
||||
|
||||
depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[1]).r;
|
||||
depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[1]).r;
|
||||
depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[1]).r;
|
||||
depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[1]).r;
|
||||
|
||||
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
|
||||
coc = max(calculate_near_coc(zdepth), coc);
|
||||
|
||||
depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[2]).r;
|
||||
depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[2]).r;
|
||||
depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[2]).r;
|
||||
depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[2]).r;
|
||||
|
||||
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
|
||||
coc = max(calculate_near_coc(zdepth), coc);
|
||||
|
||||
final_coc = max(max(coc.x, coc.y), max(coc.z, coc.w));
|
||||
gl_FragColor = vec4(color.rgb, final_coc);
|
||||
}
|
||||
|
||||
/* second pass, gaussian blur the downsampled image */
|
||||
void second_pass()
|
||||
{
|
||||
vec4 depth = vec4(texture2D(depthbuffer, uvcoordsvar.xy).r);
|
||||
|
||||
/* clever sampling to sample 2 pixels at once. Of course it's not real gaussian sampling this way */
|
||||
vec4 color = texture2D(colorbuffer, uvcoordsvar.xy) * 0.3125;
|
||||
color += texture2D(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
|
||||
color += texture2D(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
|
||||
color += texture2D(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
|
||||
color += texture2D(colorbuffer, uvcoordsvar.xy -invrendertargetdim) * 0.234375;
|
||||
color += texture2D(colorbuffer, uvcoordsvar.xy -2.5 * invrendertargetdim) * 0.09375;
|
||||
color += texture2D(colorbuffer, uvcoordsvar.xy -4.5 * invrendertargetdim) * 0.015625;
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
||||
|
||||
/* third pass, calculate the final coc from blurred and unblurred images */
|
||||
void third_pass()
|
||||
{
|
||||
vec4 color = texture2D(colorbuffer, uvcoordsvar.xy);
|
||||
vec4 color_blurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
|
||||
float coc = 2.0 * max(color_blurred.a, color.a); - color.a;
|
||||
gl_FragColor = vec4(color.rgb, coc);
|
||||
}
|
||||
|
||||
|
||||
/* fourth pass, blur the final coc once to get rid of discontinuities */
|
||||
void fourth_pass()
|
||||
{
|
||||
vec4 color = texture2D(colorbuffer, uvcoordsvar.xz);
|
||||
color += texture2D(colorbuffer, uvcoordsvar.yz);
|
||||
color += texture2D(colorbuffer, uvcoordsvar.xw);
|
||||
color += texture2D(colorbuffer, uvcoordsvar.yw);
|
||||
|
||||
gl_FragColor = color / 4.0;
|
||||
}
|
||||
|
||||
vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
|
||||
{
|
||||
float weight = 1.0/ 17.0;
|
||||
vec4 result = weight * color;
|
||||
weight *= 4.0;
|
||||
|
||||
result += weight * texture2D(colorbuffer, uv + color_uv1.xy);
|
||||
result += weight * texture2D(colorbuffer, uv - color_uv1.xy);
|
||||
result += weight * texture2D(colorbuffer, uv + color_uv1.yx);
|
||||
result += weight * texture2D(colorbuffer, uv - color_uv1.yx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* fourth pass, just visualize the third pass contents */
|
||||
void fifth_pass()
|
||||
{
|
||||
vec4 factors;
|
||||
vec4 color_orig = texture2D(colorbuffer, uvcoordsvar.xy);
|
||||
vec4 highblurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
|
||||
vec4 mediumblurred = texture2D(mblurredcolorbuffer, uvcoordsvar.xy);
|
||||
vec4 smallblurred = small_sample_blur(colorbuffer, uvcoordsvar.xy, color_orig);
|
||||
float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
|
||||
|
||||
float zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth)).r;
|
||||
float coc_far = clamp(calculate_far_coc(zdepth), 0.0, 1.0);
|
||||
|
||||
/* calculate final coc here */
|
||||
float coc = max(max(coc_far, mediumblurred.a), 0.0);
|
||||
|
||||
float width = 2.5;
|
||||
float radius = 0.2;
|
||||
|
||||
factors.x = 1.0 - clamp(width * coc, 0.0, 1.0);
|
||||
factors.y = 1.0 - clamp(abs(width * (coc - 2.0 * radius)), 0.0, 1.0);
|
||||
factors.z = 1.0 - clamp(abs(width * (coc - 3.0 * radius)), 0.0, 1.0);
|
||||
factors.w = 1.0 - clamp(abs(width * (coc - 4.0 * radius)), 0.0, 1.0);
|
||||
/* blend! */
|
||||
vec4 color = factors.x * color_orig + factors.y * smallblurred + factors.z * mediumblurred + factors.w * highblurred;
|
||||
|
||||
color /= dot(factors, vec4(1.0));
|
||||
gl_FragColor = vec4(color.rgb, 1.0);
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef FIRST_PASS
|
||||
first_pass();
|
||||
#elif defined(SECOND_PASS)
|
||||
second_pass();
|
||||
#elif defined(THIRD_PASS)
|
||||
third_pass();
|
||||
#elif defined(FOURTH_PASS)
|
||||
fourth_pass();
|
||||
#elif defined(FIFTH_PASS)
|
||||
fifth_pass();
|
||||
#endif
|
||||
}
|
68
source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
Normal file
68
source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
Normal file
@@ -0,0 +1,68 @@
|
||||
uniform vec2 invrendertargetdim;
|
||||
|
||||
//texture coordinates for framebuffer read
|
||||
varying vec4 uvcoordsvar;
|
||||
|
||||
/* color texture coordinates, offset by a small amount */
|
||||
varying vec2 color_uv1;
|
||||
varying vec2 color_uv2;
|
||||
|
||||
varying vec2 depth_uv1;
|
||||
varying vec2 depth_uv2;
|
||||
varying vec2 depth_uv3;
|
||||
varying vec2 depth_uv4;
|
||||
|
||||
//very simple shader for gull screen FX, just pass values on
|
||||
|
||||
void vert_generic()
|
||||
{
|
||||
uvcoordsvar = gl_MultiTexCoord0;
|
||||
gl_Position = gl_Vertex;
|
||||
}
|
||||
|
||||
void vert_dof_first_pass()
|
||||
{
|
||||
/* we offset the texture coordinates by 1.5 pixel,
|
||||
* then we reuse that to sample the surrounding pixels */
|
||||
color_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
|
||||
color_uv2 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
|
||||
|
||||
depth_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
|
||||
depth_uv2 = gl_MultiTexCoord0.xy + vec2(-0.5, -1.5) * invrendertargetdim;
|
||||
depth_uv3 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
|
||||
depth_uv4 = gl_MultiTexCoord0.xy + vec2(1.5, -1.5) * invrendertargetdim;
|
||||
|
||||
gl_Position = gl_Vertex;
|
||||
}
|
||||
|
||||
void vert_dof_fourth_pass()
|
||||
{
|
||||
vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
|
||||
uvcoordsvar = gl_MultiTexCoord0.xxyy + halfpixel * vec4(invrendertargetdim.x,
|
||||
invrendertargetdim.x, invrendertargetdim.y, invrendertargetdim.y);
|
||||
|
||||
gl_Position = gl_Vertex;
|
||||
}
|
||||
|
||||
void vert_dof_fifth_pass()
|
||||
{
|
||||
vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
|
||||
color_uv1 = vec2(0.5, 1.5) * invrendertargetdim;
|
||||
|
||||
uvcoordsvar = gl_MultiTexCoord0;
|
||||
gl_Position = gl_Vertex;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef FIRST_PASS
|
||||
vert_dof_first_pass();
|
||||
#elif defined(FOURTH_PASS)
|
||||
vert_dof_fourth_pass();
|
||||
#elif defined(FIFTH_PASS)
|
||||
vert_dof_fifth_pass();
|
||||
#else
|
||||
vert_generic();
|
||||
#endif
|
||||
}
|
||||
|
47
source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
Normal file
47
source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
Normal file
@@ -0,0 +1,47 @@
|
||||
vec3 calculate_view_space_normal(in vec3 viewposition)
|
||||
{
|
||||
vec3 normal = cross(normalize(dFdx(viewposition)),
|
||||
normalize(dFdy(viewposition)));
|
||||
normalize(normal);
|
||||
return normal;
|
||||
}
|
||||
|
||||
/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer
|
||||
* we change the factors from the article to fit the OpennGL model. */
|
||||
#ifdef PERSP_MATRIX
|
||||
|
||||
/* perspective camera code */
|
||||
|
||||
vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
|
||||
{
|
||||
float d = 2.0 * depth - 1.0;
|
||||
|
||||
float zview = -gl_ProjectionMatrix[3][2] / (d + gl_ProjectionMatrix[2][2]);
|
||||
|
||||
return zview * (viewvec_origin + vec3(uvcoords, 0.0) * viewvec_diff);
|
||||
}
|
||||
|
||||
vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
|
||||
{
|
||||
vec4 d = 2.0 * depth - vec4(1.0);
|
||||
|
||||
/* return positive value, so sign differs! */
|
||||
return vec4(gl_ProjectionMatrix[3][2]) / (d + vec4(gl_ProjectionMatrix[2][2]));
|
||||
}
|
||||
|
||||
#else
|
||||
/* orthographic camera code */
|
||||
|
||||
vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
|
||||
{
|
||||
vec3 offset = vec3(uvcoords, depth);
|
||||
|
||||
return vec3(viewvec_origin + offset * viewvec_diff);
|
||||
}
|
||||
|
||||
vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
|
||||
{
|
||||
return -(near + depth * range);
|
||||
}
|
||||
|
||||
#endif
|
82
source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
Normal file
82
source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
Normal file
@@ -0,0 +1,82 @@
|
||||
// color buffer
|
||||
uniform sampler2D colorbuffer;
|
||||
|
||||
// jitter texture for ssao
|
||||
uniform sampler2D jitter_tex;
|
||||
|
||||
// concentric sample texture for ssao
|
||||
uniform sampler1D ssao_concentric_tex;
|
||||
|
||||
// depth buffer
|
||||
uniform sampler2D depthbuffer;
|
||||
// coordinates on framebuffer in normalized (0.0-1.0) uv space
|
||||
varying vec4 uvcoordsvar;
|
||||
|
||||
/* ssao_params.x : pixel scale for the ssao radious */
|
||||
/* ssao_params.y : factor for the ssao darkening */
|
||||
uniform vec4 ssao_params;
|
||||
uniform vec4 ssao_sample_params;
|
||||
uniform vec4 ssao_color;
|
||||
|
||||
/* store the view space vectors for the corners of the view frustum here.
|
||||
* It helps to quickly reconstruct view space vectors by using uv coordinates,
|
||||
* see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
|
||||
uniform vec4 viewvecs[3];
|
||||
|
||||
float calculate_ssao_factor(float depth)
|
||||
{
|
||||
/* take the normalized ray direction here */
|
||||
vec2 rotX = texture2D(jitter_tex, uvcoordsvar.xy * ssao_sample_params.zw).rg;
|
||||
vec2 rotY = vec2(-rotX.y, rotX.x);
|
||||
|
||||
/* occlusion is zero in full depth */
|
||||
if (depth == 1.0)
|
||||
return 0.0;
|
||||
|
||||
vec3 position = get_view_space_from_depth(uvcoordsvar.xy, viewvecs[0].xyz, viewvecs[1].xyz, depth);
|
||||
vec3 normal = calculate_view_space_normal(position);
|
||||
|
||||
// find the offset in screen space by multiplying a point in camera space at the depth of the point by the projection matrix.
|
||||
vec2 offset;
|
||||
float homcoord = gl_ProjectionMatrix[2][3] * position.z + gl_ProjectionMatrix[3][3];
|
||||
offset.x = gl_ProjectionMatrix[0][0] * ssao_params.x / homcoord;
|
||||
offset.y = gl_ProjectionMatrix[1][1] * ssao_params.x / homcoord;
|
||||
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
|
||||
offset *= 0.5;
|
||||
|
||||
float factor = 0.0;
|
||||
int x;
|
||||
int num_samples = int(ssao_sample_params.x);
|
||||
|
||||
for (x = 0; x < num_samples; x++) {
|
||||
vec2 dir_sample = texture1D(ssao_concentric_tex, (float(x) + 0.5) / ssao_sample_params.x).rg;
|
||||
|
||||
/* rotate with random direction to get jittered result */
|
||||
vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY));
|
||||
|
||||
vec2 uvcoords = uvcoordsvar.xy + dir_jittered * offset;
|
||||
|
||||
float depth_new = texture2D(depthbuffer, uvcoords).r;
|
||||
if (depth_new != 1.0) {
|
||||
vec3 pos_new = get_view_space_from_depth(uvcoords, viewvecs[0].xyz, viewvecs[1].xyz, depth_new);
|
||||
vec3 dir = pos_new - position;
|
||||
float len = length(dir);
|
||||
float f = dot(dir, normal);
|
||||
|
||||
/* use minor bias here to avoid self shadowing */
|
||||
if (f > 0.05 * len + 0.0001)
|
||||
factor += f * 1.0/(len * (1.0 + len * len * ssao_params.z));
|
||||
}
|
||||
}
|
||||
|
||||
factor /= ssao_sample_params.x;
|
||||
|
||||
return clamp(factor * ssao_params.y, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
|
||||
vec4 color = mix(texture2D(colorbuffer, uvcoordsvar.xy), ssao_color, calculate_ssao_factor(depth));
|
||||
gl_FragColor = vec4(color.rgb, 1.0);
|
||||
}
|
9
source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
Normal file
9
source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
Normal file
@@ -0,0 +1,9 @@
|
||||
varying vec4 uvcoordsvar;
|
||||
|
||||
//very simple shader for full screen FX, just pass values on
|
||||
|
||||
void main()
|
||||
{
|
||||
uvcoordsvar = gl_MultiTexCoord0;
|
||||
gl_Position = gl_Vertex;
|
||||
}
|
@@ -33,7 +33,7 @@
|
||||
#define __DNA_CAMERA_TYPES_H__
|
||||
|
||||
#include "DNA_defs.h"
|
||||
|
||||
#include "DNA_gpu_types.h"
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -65,6 +65,7 @@ typedef struct Camera {
|
||||
struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */
|
||||
|
||||
struct Object *dof_ob;
|
||||
struct GPUDOFSettings gpu_dof;
|
||||
|
||||
char sensor_fit;
|
||||
char pad[7];
|
||||
|
66
source/blender/makesdna/DNA_gpu_types.h
Normal file
66
source/blender/makesdna/DNA_gpu_types.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file DNA_gpu_types.h
|
||||
* \ingroup DNA
|
||||
*/
|
||||
|
||||
#ifndef __DNA_GPU_TYPES_H__
|
||||
#define __DNA_GPU_TYPES_H__
|
||||
|
||||
/* properties for dof effect */
|
||||
typedef struct GPUDOFSettings {
|
||||
float focus_distance; /* focal distance for depth of field */
|
||||
float fstop;
|
||||
float focal_length;
|
||||
float sensor;
|
||||
} GPUDOFSettings;
|
||||
|
||||
/* properties for SSAO effect */
|
||||
typedef struct GPUSSAOSettings {
|
||||
float factor;
|
||||
float color[3];
|
||||
float distance_max;
|
||||
float attenuation;
|
||||
int samples; /* ray samples, we use presets here for easy control instead of */
|
||||
int pad;
|
||||
} GPUSSAOSettings;
|
||||
|
||||
typedef struct GPUFXSettings {
|
||||
GPUDOFSettings *dof;
|
||||
GPUSSAOSettings *ssao;
|
||||
char fx_flag; /* eGPUFXFlags */
|
||||
char pad[7];
|
||||
} GPUFXSettings;
|
||||
|
||||
/* shaderfx enables */
|
||||
typedef enum eGPUFXFlags {
|
||||
GPU_FX_FLAG_DOF = (1 << 0),
|
||||
GPU_FX_FLAG_SSAO = (1 << 1),
|
||||
} eGPUFXFlags;
|
||||
|
||||
#endif /* __DNA_GPU_TYPES_H__ */
|
@@ -46,6 +46,7 @@ extern "C" {
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_freestyle_types.h"
|
||||
#include "DNA_gpu_types.h"
|
||||
|
||||
struct CurveMapping;
|
||||
struct Object;
|
||||
|
@@ -46,6 +46,7 @@ struct bGPdata;
|
||||
struct SmoothView3DStore;
|
||||
struct wmTimer;
|
||||
struct Material;
|
||||
struct GPUFX;
|
||||
|
||||
/* This is needed to not let VC choke on near and far... old
|
||||
* proprietary MS extensions... */
|
||||
@@ -60,6 +61,7 @@ struct Material;
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_image_types.h"
|
||||
#include "DNA_movieclip_types.h"
|
||||
#include "DNA_gpu_types.h"
|
||||
|
||||
/* ******************************** */
|
||||
|
||||
@@ -146,6 +148,7 @@ typedef struct RegionView3D {
|
||||
float rot_angle;
|
||||
float rot_axis[3];
|
||||
|
||||
struct GPUFX *compositor;
|
||||
} RegionView3D;
|
||||
|
||||
/* 3D ViewPort Struct */
|
||||
@@ -210,11 +213,17 @@ typedef struct View3D {
|
||||
struct ListBase afterdraw_transp;
|
||||
struct ListBase afterdraw_xray;
|
||||
struct ListBase afterdraw_xraytransp;
|
||||
|
||||
|
||||
/* drawflags, denoting state */
|
||||
char zbuf, transp, xray;
|
||||
|
||||
/* built-in shader effects (eGPUFXFlags) */
|
||||
char pad3[5];
|
||||
|
||||
/* note, 'fx_settings.dof' is currently _not_ allocated,
|
||||
* instead set (temporarily) from camera */
|
||||
struct GPUFXSettings fx_settings;
|
||||
|
||||
void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */
|
||||
struct Material *defmaterial; /* used by matcap now */
|
||||
|
||||
|
@@ -73,6 +73,7 @@ static const char *includefiles[] = {
|
||||
"DNA_key_types.h",
|
||||
"DNA_text_types.h",
|
||||
"DNA_packedFile_types.h",
|
||||
"DNA_gpu_types.h",
|
||||
"DNA_camera_types.h",
|
||||
"DNA_image_types.h",
|
||||
"DNA_texture_types.h",
|
||||
|
@@ -284,8 +284,6 @@ void RNA_def_camera(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Lens Unit", "Unit to edit lens in for the user interface");
|
||||
|
||||
/* pointers */
|
||||
rna_def_animdata_common(srna);
|
||||
|
||||
prop = RNA_def_property(srna, "dof_object", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Object");
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "dof_ob");
|
||||
@@ -293,6 +291,13 @@ void RNA_def_camera(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "DOF Object", "Use this object to define the depth of field focal point");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "gpu_dof", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "GPUDOFSettings");
|
||||
RNA_def_property_ui_text(prop, "GPU Depth Of Field", "");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
|
||||
rna_def_animdata_common(srna);
|
||||
|
||||
/* Camera API */
|
||||
RNA_api_camera(srna);
|
||||
}
|
||||
|
@@ -1692,6 +1692,28 @@ static void rna_FreestyleSettings_module_remove(ID *id, FreestyleSettings *confi
|
||||
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
|
||||
}
|
||||
|
||||
char *rna_GPUDOF_path(PointerRNA *ptr)
|
||||
{
|
||||
/* if there is ID-data, resolve the path using the index instead of by name,
|
||||
* since the name used is the name of the texture assigned, but the texture
|
||||
* may be used multiple times in the same stack
|
||||
*/
|
||||
if (ptr->id.data) {
|
||||
if (GS(((ID *)ptr->id.data)->name) == ID_CA) {
|
||||
return BLI_strdup("gpu_dof");
|
||||
}
|
||||
}
|
||||
|
||||
return BLI_strdup("");;
|
||||
}
|
||||
|
||||
static void rna_GPUFXSettings_fx_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
GPUFXSettings *fx_settings = ptr->data;
|
||||
|
||||
BKE_screen_gpu_fx_validate(fx_settings);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_transform_orientation(BlenderRNA *brna)
|
||||
@@ -3822,6 +3844,114 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
|
||||
rna_def_scene_game_recast_data(brna);
|
||||
}
|
||||
|
||||
static void rna_def_gpu_dof_fx(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "GPUDOFSettings", NULL);
|
||||
RNA_def_struct_ui_text(srna, "GPU DOF", "Settings for GPU based depth of field");
|
||||
RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
|
||||
RNA_def_struct_path_func(srna, "rna_GPUDOF_path");
|
||||
|
||||
prop = RNA_def_property(srna, "focus_distance", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_ui_text(prop, "Focus distance", "Viewport depth of field focus distance");
|
||||
RNA_def_property_range(prop, 0.0f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "focal_length", PROP_FLOAT, PROP_DISTANCE_CAMERA);
|
||||
RNA_def_property_ui_text(prop, "Focal Length", "Foca Length for dof effect");
|
||||
RNA_def_property_range(prop, 1.0f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "sensor", PROP_FLOAT, PROP_DISTANCE_CAMERA);
|
||||
RNA_def_property_ui_text(prop, "Sensor", "Size of sensor");
|
||||
RNA_def_property_range(prop, 1.0f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "fstop", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "F/Stop", "FStop for dof effect");
|
||||
RNA_def_property_range(prop, 0.0f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_gpu_ssao_fx(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "GPUSSAOSettings", NULL);
|
||||
RNA_def_struct_ui_text(srna, "GPU SSAO", "Settings for GPU based screen space ambient occlusion");
|
||||
RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
|
||||
|
||||
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Strength", "Strength of the ssao effect");
|
||||
RNA_def_property_range(prop, 0.0f, 250.0f);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "distance_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the SSAO effect");
|
||||
RNA_def_property_range(prop, 0.0f, 100000.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "attenuation", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
|
||||
RNA_def_property_range(prop, 1.0f, 100000.0f);
|
||||
RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Samples", "Number of samples. Final number is squared");
|
||||
RNA_def_property_range(prop, 1, 30); /* 0 is needed for compression. */
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_ui_text(prop, "SSAO Color", "Color for screen space ambient occlusion effect");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void rna_def_gpu_fx(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
rna_def_gpu_ssao_fx(brna);
|
||||
rna_def_gpu_dof_fx(brna);
|
||||
|
||||
srna = RNA_def_struct(brna, "GPUFXSettings", NULL);
|
||||
RNA_def_struct_ui_text(srna, "GPU FX Settings", "Settings for GPU based compositing");
|
||||
RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
|
||||
|
||||
prop = RNA_def_property(srna, "dof", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_struct_type(prop, "GPUDOFSettings");
|
||||
RNA_def_property_ui_text(prop, "Depth Of Field settings", "");
|
||||
|
||||
prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_DOF);
|
||||
RNA_def_property_ui_text(prop, "Depth Of Field", "Use depth of field on viewport using the values from active camera");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update");
|
||||
|
||||
|
||||
prop = RNA_def_property(srna, "ssao", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_struct_type(prop, "GPUSSAOSettings");
|
||||
RNA_def_property_ui_text(prop, "Screen Space Ambient Occlusion settings", "");
|
||||
|
||||
prop = RNA_def_property(srna, "use_ssao", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_SSAO);
|
||||
RNA_def_property_ui_text(prop, "SSAO", "Use screen space ambient occlusion of field on viewport");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update");
|
||||
}
|
||||
|
||||
|
||||
static void rna_def_scene_render_layer(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -5862,7 +5992,9 @@ void RNA_def_scene(BlenderRNA *brna)
|
||||
/* *** Animated *** */
|
||||
rna_def_scene_render_data(brna);
|
||||
rna_def_scene_render_layer(brna);
|
||||
|
||||
|
||||
rna_def_gpu_fx(brna);
|
||||
|
||||
/* Scene API */
|
||||
RNA_api_scene(srna);
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_movieclip.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_key_types.h"
|
||||
@@ -2128,7 +2129,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
srna = RNA_def_struct(brna, "SpaceView3D", "Space");
|
||||
RNA_def_struct_sdna(srna, "View3D");
|
||||
RNA_def_struct_ui_text(srna, "3D View Space", "3D View space data");
|
||||
@@ -2470,6 +2470,10 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture, active objects only");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_matcap_update");
|
||||
|
||||
prop = RNA_def_property(srna, "fx_settings", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "FX Options", "Options used for real time compositing");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
/* region */
|
||||
|
||||
srna = RNA_def_struct(brna, "RegionView3D", NULL);
|
||||
|
Reference in New Issue
Block a user