1
1

Compare commits

...

114 Commits

Author SHA1 Message Date
5515e5727b Final nitpicks:
No warning for out of camera, rename darken to factor/strength (since
color can be actually be light)
2015-02-12 18:45:36 +01:00
c1e9df7e79 replace 'SSAO' option with 'Ambient Occlusion'
more descriptive, and SSAO is more for developers/shader writers
2015-02-13 04:43:55 +11:00
2a2d90e6e0 error in last commit 2015-02-13 04:40:06 +11:00
55e206c580 use common GPU_fx_compositor_ prefix
also rename darkening -> darken
2015-02-13 04:38:07 +11:00
761e8ef733 Tidy up the UI a bit for DOF 2015-02-12 18:36:32 +01:00
f43f4f0e89 Add initialization functions for GPU compositing 2015-02-12 18:26:03 +01:00
6719fb8248 move comment to view3d 2015-02-13 04:21:11 +11:00
617fc1f49e correction to last comment 2015-02-13 04:19:22 +11:00
eedd9b70b6 Comment out DOF initialization, its not used
This is a special case
2015-02-13 04:18:20 +11:00
ccd3fb8ea7 Also write DOF if it exists. 2015-02-12 18:15:15 +01:00
9ef1a6b2f2 Move fx_flag into the GPUFXSettings struct (simplifies things a bit) 2015-02-13 04:09:52 +11:00
c28f3e3e0a Various changes:
- use term 'settings' rather then 'options', (follows rest of rna)
- use const where possible
- minor changes to arg order
2015-02-13 03:36:11 +11:00
78aa9be2ee Merge branch 'master' into viewport_master_merge 2015-02-12 16:19:35 +01:00
d5b99ceb55 3D Viewport only uses DOF when rendered from camera now. 2015-02-12 16:18:17 +01:00
3fa8fad5f1 Reuse focal length and sensor from camera 2015-02-12 15:43:41 +01:00
7064313ec6 More naming tidying up 2015-02-12 15:38:27 +01:00
4f5e9f0857 Don't allocate FX, naming of eGPUFXFlags 2015-02-12 15:12:16 +01:00
7409fddf27 Cleanup naming, use sane defaults 2015-02-12 14:54:45 +01:00
4557ad66c1 Minor simplification 2015-02-10 17:32:22 +01:00
dc506fba9c Cleanup redundant state changes 2015-02-10 16:45:02 +01:00
4eb6b35926 Use an enum for enabled GPU Fx 2015-02-10 16:39:26 +01:00
0d8b701e25 Forward compatibility: Use triangle strips instead of quads 2015-02-10 16:29:10 +01:00
bdfd9ba38a Cleanup leftover code from WIP renderer 2015-02-10 12:57:47 +01:00
0ea64c2b9a More cleanup 2015-02-10 11:55:13 +01:00
9d1336b653 Framebuffer effects:
This includes offscreen processing for the 3D viewport and OpenGL rendering.

Included effects are a depth of field shader and a Screen Space Ambient
Occlusion shader.

The system is simplistic and duplicates some code. I am in the process of making abstractions
so the effects can be used in a node system, but we can probably give users
access to the early system right now.

Reviewers: sergey, campbellbarton, jwilkins, merwin

Differential Revision: https://developer.blender.org/D1092
2015-02-10 11:49:22 +01:00
b7c1d2e898 Cleanup - bring branch to merge ready condition 2015-02-10 11:34:47 +01:00
268ae6a62b Merge branch 'master' into viewport_experiments 2015-02-10 11:18:12 +01:00
7d1e7de7be Merge branch 'master' into viewport_experiments
Conflicts:
	CMakeLists.txt
2015-02-03 19:29:37 +01:00
28f271736b Cleanup for compositing, move to c++ WIP node abstractions for compositing system. 2015-02-03 19:27:33 +01:00
8a8e29ac6a Select appropriate folder for MinGW-w64 gcc 4.9 2015-01-16 15:02:48 +02:00
a75728341b Fix T43208 material flickering in edit mode.
Happens because material setting now occurs in the derived mesh drawing
routine as it should. However that means that it also happens during
selection and that influenced the drawing state somehow.

In 2.72 this did not occur because material setting happened during draw
setting (skip or draw) instead of after the draw setting passed (so
selection would skip it by use another draw setting function). Of course
this violated design but worked.

Made it now so backbuffer selection does not enable materials (it's
redundant in those cases anyway).

This could be ported to a possible 'a' release but as is classic with
display code there may be some other places that it could backfire.

Tested fix with texture/vertex painting and selection which use
backbuffer for both subsurf and regular meshes and it seems to work OK.
2015-01-11 21:28:30 +01:00
da94a7005a Add initial compositing node API, compositing code already becomes too
redundant and hard for prototyping. This will make things easier.
2015-01-09 16:48:59 +01:00
568c8b7b55 Merge branch 'master' into viewport_experiments 2015-01-09 12:51:29 +01:00
6148295f1a fragment shader to downsample near circle of confusion - rename texture
coordinates so it's clearer they are reusable.
2015-01-06 20:27:52 +01:00
0790db4f5c signed coc matches the low quality one. 2015-01-06 20:01:32 +01:00
1cfb12ddbf As usually hard to find errors are usually quite silly. We can now see
the coc value
2015-01-06 19:41:24 +01:00
27fe02f213 Intermediate commit.
Basically, we try to output coc values to a second render target, but
apparently OpenGL somehow hates us. Committing so that Mac may give a
better diagnostic on what is happening.
2015-01-06 19:16:16 +01:00
79b8540e66 First stage of better dof, downsample buffer by half. 2015-01-06 17:57:25 +01:00
fd1036e803 Add new shader files to Scons 2015-01-06 15:49:59 +01:00
08cc519e79 WIP for new dof 2015-01-06 15:03:24 +01:00
b06999435a Pass enumerants for new shader effect. WIP commit to continue later. 2015-01-05 19:25:21 +01:00
9ca9bb68af Depth of field: initialize textures for better algorithm. 2015-01-05 19:05:41 +01:00
f54d210f26 Use nice switch statement instead of horrible chained ifs. 2015-01-05 18:09:40 +01:00
e306e99574 Merge branch 'master' into viewport_experiments
Making clamping correct fixes the issues of depth of field having a dark
fringe at the edges of the screen.
2015-01-05 14:38:33 +01:00
85e9ddd515 Fix SSAO artifacts at zero distance by using a small constant bias in
length comparison.
2015-01-05 14:11:37 +01:00
63ab9c1089 Merge branch 'master' into viewport_experiments
Conflicts:
	source/blender/blenkernel/intern/camera.c
2015-01-05 11:30:19 +01:00
dbf18d88fc Add request for HDR targets - all compositing is done in HDR targets
now.
2015-01-02 19:21:26 +01:00
a4c154bc5a Disable bound textures just in case they come and bite us somewhere
unpleasant.
2015-01-02 17:12:37 +01:00
2a189a0546 SSAO - use concentric mapping.
Concentric mapping is a nice way to create a circular distribution from
orthogonal 2D coordinates. Using this allows us to expose directly the
number of samples to the user instead of quality options.

Concentric mapping will likely be used for DOF sampling too later.

References:

[1] A Low Distortion Map Between Disk and Square - Peter Shirley,
Kenneth Chiu

[2] http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-
2015-01-02 16:57:41 +01:00
376a004b26 Merge branch 'master' into viewport_experiments 2015-01-02 13:47:26 +01:00
4ca945778f cleanup diffusion dof names and add blade count (will possibly be used in high quality) 2014-12-23 14:02:46 +01:00
4d6d8b8c14 Merge branch 'master' into viewport_experiments 2014-12-22 12:50:14 +01:00
702cb6c403 Replace magic quality numbers, add some cleanup code, deactivate high
quality mode dof.
2014-12-06 01:09:26 +01:00
c37c50e33f Add quality settings for depth of field - still inactive. 2014-12-06 00:32:04 +01:00
44e8045ee5 Merge branch 'master' into viewport_experiments 2014-12-05 23:32:07 +01:00
5467064777 Merge branch 'master' into viewport_experiments
Conflicts:
	source/blender/editors/space_view3d/view3d_draw.c
	source/blender/gpu/GPU_buffers.h
	source/blender/gpu/intern/gpu_buffers.c
2014-11-28 16:15:13 +01:00
bd434b92b6 Revert "Hook up flags to request a specific sorting scheme from GPU buffer setup"
This reverts commit 827ad6075d.
2014-11-28 16:10:25 +01:00
5373b4a8b1 Merge branch 'master' into viewport_experiments
Conflicts:
	source/blender/editors/space_view3d/view3d_draw.c
	source/blender/gpu/intern/gpu_extensions.c
2014-11-25 16:31:55 +01:00
ec69df6147 Merge branch 'master' into viewport_experiments 2014-11-18 17:47:56 +01:00
40b1d29ec7 Merge branch 'master' into viewport_experiments
Conflicts:
	source/blender/gpu/intern/gpu_extensions.c
2014-11-18 13:49:57 +01:00
3021399869 Ensure View3D fx when using them, prevents some crashes with old files 2014-11-14 23:52:41 +01:00
ace38bdc82 Fix SSAO not being constant in camera view. 2014-11-14 19:55:30 +01:00
cb94f59f71 Fix T42596 crash with DOF on MacOS.
Compiler failed on last shader and failure was not detected. However
compiler error also revealed a blurring error as well :)
2014-11-14 14:45:20 +01:00
63d7d8e1e5 Merge branch 'master' into viewport_experiments 2014-11-14 14:07:47 +01:00
43d4a56d8d Support animation of camera dof properties.
Also minor cleanup
2014-11-04 17:02:08 +01:00
7b0031b187 Avoid freeing and reading/writing NULL pointers. Should not happen often
but better guard against it.
2014-11-04 15:26:25 +01:00
4322085f4f Only show properties if not in camera view, else direct user to camera
properties
2014-11-04 15:25:55 +01:00
4aad147fe4 Support camera GPU parameters when looking/rendering through camera in
the viewport.
2014-11-04 14:30:19 +01:00
b550e788f2 Use own file for GPU option types.
* Add gpu options for depth of field to camera - still inactive.
* GPUFXOptions now passed to the compositing system startup
so users can swap options if they wish to

This commit changes read-write data again, people should reset their
values again (sorry for that but this is still WIP)
2014-11-04 14:30:19 +01:00
46cc844f43 Offscreen rendering for viewport FX.
This is working mostly from the 3D viewport currently, rendering from
the render buttons or the sequencer will not use the FX yet. Still it's
a solid step towards that direction. Also moved options out of the v3d
struct. Old options will be lost and people may get some warnings,
however simply enableing and disabling one of the compositing settings
will bring the controls back.
2014-11-03 20:20:32 +01:00
7798ecd743 Add another level of small blur to bridge between no/medium blurring.
Algorithm used is now a full implementation of

"Practical Post-Process depth of field", presented here [1],
with a few modifications as to how circle of confusion is
applied at the final pass.

[1] http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html
2014-11-03 14:06:47 +01:00
78d42f7885 Merge branch 'master' into viewport_experiments 2014-11-03 09:56:49 +01:00
eb8a09d567 DOF effect works :) 2014-10-31 21:23:57 +01:00
2a5556b426 Merge branch 'master' into viewport_experiments 2014-10-31 14:45:00 +01:00
de27811177 Correctly downsample circles of confusion and use parallelism to do it
more efficient.
2014-10-29 19:41:12 +01:00
6484056cc1 Second pass, blurs the downsampled buffer once. 2014-10-29 18:31:15 +01:00
a4f35de026 Use the correct shaders and varyings 2014-10-29 18:08:22 +01:00
ba2f0ad779 Viewport DOF:
* Scons builds correctly
* Separate vertex shader file for DOF, will make handling main easier
* Downsample color buffer + blur it. Circle of confusion is calculated
from zplane instead of length of distance from camera.
2014-10-29 16:18:19 +01:00
e0cba973e7 First ping pong between low resolution buffers working. Nice landmark
for working code.

Also cleanup unused variables and do not bind the same texture to two slots
(blurred texture is going to be different anyway)
2014-10-29 12:46:25 +01:00
c6292918a3 Framebuffer compositing:
* Cleanup compositing buffers better when not needed.

* Support passes for the dof effect through defines in main - easy
solution to allow not having too many files for one shader effect.
2014-10-29 12:01:13 +01:00
518f794a6f SSAO and DOF work well together now. 2014-10-29 11:12:41 +01:00
dc22a50488 Code that enables simultaneous DOF-SSAO effect. There's some sort of
texture coordinate offset still.
2014-10-28 21:24:38 +01:00
d2d3bd35c1 Use optimized view space reconstruction for ortho case as well. 2014-10-28 19:44:05 +01:00
0782c680a6 Add a library file for projection shader code, should enable us to use
optimized position calculation again - relevant for both SSAO and DOF
2014-10-28 19:07:58 +01:00
8f25b6d6c8 More attempts to synchronize viewport and camera dof - probably will
need fixes in the rendering systems. Reserve textures for the dof
effect.
2014-10-28 18:28:58 +01:00
6e8ba2f3f5 DOF calculation shader. 2014-10-27 20:45:51 +01:00
c48abbb090 Merge branch 'master' into viewport_experiments 2014-10-27 11:10:49 +01:00
5efa0e03b5 Add separate file for DOF effect and cleanup the parameter passing a little. 2014-10-27 10:06:56 +01:00
d54c249a7b Separate SSAO pass - it's unlikely we'll be able to reuse this with
depth of field in one pass, so better separate the shaders as well
2014-10-23 22:42:48 +02:00
3967f5659d Fix irritating issue with self shadowing.
Issue here was position reconstruction could use depths from pixels off
the initial position. Using linear filtering here eliminates the issue.

Usually this is not correct however given that for depth discontinuities
we will get different depths anyway, the cases where we get smooth
interpolation of depths helps a lot in image quality.
2014-10-23 20:12:39 +02:00
1082a2f125 Add some pedantic GLSL casts to make shader compile in OSX 2014-10-23 17:01:19 +02:00
ddb33a3181 SSAO introduce quality settings
Basically change the way SSAO samples the screen by using a circular
filter instead. This is inspired by HBAO though we still don't use this.

The quality settings change the number and density of samples. We can
definitely improve things here though.

We also jitter the sampling locations per pixel. Generally this adds a
kind of noise. Some banding is, unfortunately still apparent and small
distances will introduce noise. This can be fixed but I will have to see
if it can be done without much of a cost.
2014-10-22 19:27:43 +02:00
33e7e1ddb2 SSAO works again. Unfortunately it's unavoidable to have it work without
explicit attenuation control (by using just max distance).

Also it now supports orthographic cameras properly. The maximum distance is
now defined in world space units so it should be slightly easier to understand
and uniform across perspective and orthographic cameras.

The optimizations can be generalized for orthographic cameras but the code is
more complex and the runtime advantage is questionable in that case
(in the end a matrix transform is 4 dot products which are not that terrible)
so commented out the code there for now.
2014-10-22 16:33:33 +02:00
0c8469c440 Correct normal reconstruction with optimized formula.
This needed some adjustments from the formula I found on the article on
view space reconstruction, since OpenGL makes different assumptions about its
projection matrix.

SSAO does not work yet correctly under new model assumptions but we are going
to substitute with nice horizon based ambient occlusion.
2014-10-22 01:14:25 +02:00
30be0f0977 Refactoring of SSAO code. Uses some optimizations but result is different
still test file here to help with debugging.
2014-10-21 20:33:09 +02:00
e1755158c0 Merge branch 'master' into viewport_experiments 2014-10-21 16:54:24 +02:00
e963efcd19 Normalize the depth to the -1.0 to 1.0 range as well. 2014-10-20 21:46:29 +02:00
5b4b83d7e3 Add shader files to the source tree. It helps by displaying them in the
IDE
2014-10-20 20:38:50 +02:00
5c31594ab7 Merge branch 'master' into viewport_experiments 2014-10-20 18:56:00 +02:00
c4b6d60af3 Attempt to fix shader compilation in OSX. strict compilation does not
allow dividing float by integer.
2014-09-22 14:20:30 +02:00
33cee269da Custom color for SSAO 2014-09-18 21:40:45 +02:00
ce9fb0e997 Do not calculate SSAO on the background. Saves cycles on pixel shaders
as well as solves issue with SSAO artifacts around grids.
2014-09-18 21:20:46 +02:00
81a3a364b5 fix issue with scons 2014-09-16 23:56:45 +02:00
c56cf0b887 WIP, beginning of renderer system that should take care of sorting
materials properly for rendering.

-Need to check aspect system first before going too much into this-
2014-09-16 19:07:56 +02:00
827ad6075d Hook up flags to request a specific sorting scheme from GPU buffer setup
routines. (still inactive
)
2014-09-16 18:30:38 +02:00
d1ed35480e Fix issue with sculpting and SSAO.
We need to enable stenciling on the compositing FBO or we can clear
areas we don't want to clear and cause invalid depth values.
2014-09-16 14:09:21 +02:00
829addcff0 Restore texture coordinates properly 2014-09-16 11:25:05 +02:00
313b568f92 Merge branch 'master' into viewport_experiments 2014-09-16 10:26:34 +02:00
3a0d276c55 Fix for flickering, recreate the framebuffer textures in that case
(looks like it's the only way to have matching per pixel results too)
2014-09-15 20:32:49 +02:00
acdaf71bbe Move GPU compositing to its own file.
Also avoid recreating the framebuffers and gpu/color textures each
frame.

Happiness :)

There are still some glithes when scaling the areas, I'll look at those
next.
2014-09-15 20:06:34 +02:00
21f43fb13c SSAO
* Expose attenuation value - allows to change influence of far objects
* Change influence of far objects to quadratic, eliminates some extreme
fringing from far occluding surfaces.
2014-09-15 16:55:05 +02:00
2632c1308f SSAO shader.
This works by using the calculated view space normal and accumulating
coverage of a certain area by nearby pixels. There are two sliders to
control the effect:

* Scale controls the area around each pixel that the shader "collides"
against
* Darkening scales the occlusion effect.

The effect works, but due to the way the normals are calculated, the
normals are never smooth shaded (that would require a separate render
target to store them) and the edges or polygons can be too apparent.
This is not really fixable at the moment unless we move to deferred
pipeline.

The FX system is stll not well optimized and rendering does not always
work correctly, but it's good to have this out for people to play with.
2014-09-15 16:12:01 +02:00
33722d4011 Greatly improved normal calculation using view space position
derivatives.
2014-09-12 19:56:56 +02:00
9e2efd68e1 Framebuffer FX.
This commit introduces offscreen rendering for the 3D viewport.
There is test code that calculates depth and normal data
in screen space.

Currently just DOF is supported with a few parameters to control the
effect

This code recreates the framebuffer and texture objects every frame
which will make it -slow-. Use at your own risk.
2014-09-12 18:04:55 +02:00
36 changed files with 2102 additions and 72 deletions

View File

@@ -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 ---

View File

@@ -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):

View File

@@ -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):

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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(&params, &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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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)) {

View File

@@ -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;

View File

@@ -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]);

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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(&params);
/* 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(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
BKE_camera_params_compute_matrix(&params);
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);

View File

@@ -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)

View 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__

View File

@@ -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 */

View File

@@ -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"),

View File

@@ -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);

View 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;
}

View File

@@ -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

View 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
}

View 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
}

View 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

View 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);
}

View 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;
}

View File

@@ -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];

View 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__ */

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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",

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);