framework2

Форк
0
408 строк · 17.2 Кб
1
/*
2
 *  DofPass.cpp
3
 *
4
 *  Copyright (c) 2012, Neil Mendoza, http://www.neilmendoza.com
5
 *  All rights reserved. 
6
 *  
7
 *  Redistribution and use in source and binary forms, with or without 
8
 *  modification, are permitted provided that the following conditions are met: 
9
 *  
10
 *  * Redistributions of source code must retain the above copyright notice, 
11
 *    this list of conditions and the following disclaimer. 
12
 *  * Redistributions in binary form must reproduce the above copyright 
13
 *    notice, this list of conditions and the following disclaimer in the 
14
 *    documentation and/or other materials provided with the distribution. 
15
 *  * Neither the name of Neil Mendoza nor the names of its contributors may be used 
16
 *    to endorse or promote products derived from this software without 
17
 *    specific prior written permission. 
18
 *  
19
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
20
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
21
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
22
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
23
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
24
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
25
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
26
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
27
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
28
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
29
 *  POSSIBILITY OF SUCH DAMAGE. 
30
 *
31
 */
32
#include "DofAltPass.h"
33

34
namespace itg
35
{
36
    DofAltPass::DofAltPass(const ofVec2f& aspect, bool arb, float focalDepth, float focalLength, float fStop, bool showFocus) :
37
        focalDepth(focalDepth), focalLength(focalLength), fStop(fStop), showFocus(showFocus), RenderPass(aspect, arb, "dofalt")
38
    {
39
        string fragShaderSrc = STRINGIFY(
40
            /*
41
             DoF with bokeh GLSL shader v2.4
42
             by Martins Upitis (martinsh) (devlog-martinsh.blogspot.com)
43
             
44
             ----------------------
45
             The shader is Blender Game Engine ready, but it should be quite simple to adapt for your engine.
46
             
47
             This work is licensed under a Creative Commons Attribution 3.0 Unported License.
48
             So you are free to share, modify and adapt it for your needs, and even use it for commercial use.
49
             I would also love to hear about a project you are using it.
50
             
51
             Have fun,
52
             Martins
53
             ----------------------
54
             
55
             changelog:
56
             
57
             2.4:
58
             - physically accurate DoF simulation calculated from "focalDepth" ,"focalLength", "f-stop" and "CoC" parameters. 
59
             - option for artist controlled DoF simulation calculated only from "focalDepth" and individual controls for near and far blur 
60
             - added "circe of confusion" (CoC) parameter in mm to accurately simulate DoF with different camera sensor or film sizes
61
             - cleaned up the code
62
             - some optimization
63
             
64
             2.3:
65
             - new and physically little more accurate DoF
66
             - two extra input variables - focal length and aperture iris diameter
67
             - added a debug visualization of focus point and focal range
68
             
69
             2.1:
70
             - added an option for pentagonal bokeh shape
71
             - minor fixes
72
             
73
             2.0:
74
             - variable sample count to increase quality/performance
75
             - option to blur depth buffer to reduce hard edges
76
             - option to dither the samples with noise or pattern
77
             - bokeh chromatic aberration/fringing
78
             - bokeh bias to bring out bokeh edges
79
             - image thresholding to bring out highlights when image is out of focus
80
             
81
             */
82

83
            uniform sampler2D bgl_RenderedTexture;
84
            uniform sampler2D bgl_DepthTexture;
85
            uniform float bgl_RenderedTextureWidth;
86
            uniform float bgl_RenderedTextureHeight;
87
                                                     
88
            const float PI = 3.14159265;
89
                                                     
90
            float width = bgl_RenderedTextureWidth; //texture width
91
            float height = bgl_RenderedTextureHeight; //texture height
92

93
            vec2 texel = vec2(1.0/width,1.0/height);
94

95
            //uniform variables from external script
96

97
            uniform float focalDepth;  //focal distance value in meters, but you may use autofocus option below
98
            uniform float focalLength; //focal length in mm
99
            uniform float fstop; //f-stop value
100
            uniform bool showFocus; //show debug focus point and focal range (red = focal point, green = focal range)
101

102
            /* 
103
            make sure that these two values are the same for your camera, otherwise distances will be wrong.
104
            */
105

106
            float znear = 0.1; //camera clipping start
107
            float zfar = 100.0; //camera clipping end
108

109
            //------------------------------------------
110
            //user variables
111

112
            int samples = 3; //samples on the first ring
113
            int rings = 3; //ring count
114

115
            bool manualdof = false; //manual dof calculation
116
            float ndofstart = 1.0; //near dof blur start
117
            float ndofdist = 2.0; //near dof blur falloff distance
118
            float fdofstart = 1.0; //far dof blur start
119
            float fdofdist = 3.0; //far dof blur falloff distance
120

121
            float CoC = 0.03;//circle of confusion size in mm (35mm film = 0.03mm)
122

123
            bool vignetting = true; //use optical lens vignetting?
124
            float vignout = 1.3; //vignetting outer border
125
            float vignin = 0.0; //vignetting inner border
126
            float vignfade = 22.0; //f-stops till vignete fades
127

128
            bool autofocus = false; //use autofocus in shader? disable if you use external focalDepth value
129
            vec2 focus = vec2(0.5,0.5); // autofocus point on screen (0.0,0.0 - left lower corner, 1.0,1.0 - upper right)
130
            float maxblur = 1.0; //clamp value of max blur (0.0 = no blur,1.0 default)
131

132
            float threshold = 0.5; //highlight threshold;
133
            float gain = 2.0; //highlight gain;
134

135
            float bias = 0.5; //bokeh edge bias
136
            float fringe = 0.7; //bokeh chromatic aberration/fringing
137

138
            bool noise = true; //use noise instead of pattern for sample dithering
139
            float namount = 0.0001; //dither amount
140

141
            bool depthblur = false; //blur the depth buffer?
142
            float dbsize = 1.25; //depthblursize
143

144
            /*
145
            next part is experimental
146
            not looking good with small sample and ring count
147
            looks okay starting from samples = 4, rings = 4
148
            */
149

150
            bool pentagon = false; //use pentagon as bokeh shape?
151
            float feather = 0.4; //pentagon shape feather
152

153
            //------------------------------------------
154

155
            float penta(vec2 coords) //pentagonal shape
156
            {
157
                float scale = float(rings) - 1.3;
158
                vec4  HS0 = vec4( 1.0,         0.0,         0.0,  1.0);
159
                vec4  HS1 = vec4( 0.309016994, 0.951056516, 0.0,  1.0);
160
                vec4  HS2 = vec4(-0.809016994, 0.587785252, 0.0,  1.0);
161
                vec4  HS3 = vec4(-0.809016994,-0.587785252, 0.0,  1.0);
162
                vec4  HS4 = vec4( 0.309016994,-0.951056516, 0.0,  1.0);
163
                vec4  HS5 = vec4( 0.0        ,0.0         , 1.0,  1.0);
164
                
165
                vec4  one = vec4( 1.0 );
166
                
167
                vec4 P = vec4((coords),vec2(scale, scale)); 
168
                
169
                vec4 dist = vec4(0.0);
170
                float inorout = -4.0;
171
                
172
                dist.x = dot( P, HS0 );
173
                dist.y = dot( P, HS1 );
174
                dist.z = dot( P, HS2 );
175
                dist.w = dot( P, HS3 );
176
                
177
                dist = smoothstep( -feather, feather, dist );
178
                
179
                inorout += dot( dist, one );
180
                
181
                dist.x = dot( P, HS4 );
182
                dist.y = HS5.w - abs( P.z );
183
                
184
                dist = smoothstep( -feather, feather, dist );
185
                inorout += dist.x;
186
                
187
                return clamp( inorout, 0.0, 1.0 );
188
            }
189
                                                     
190
            float bdepth(vec2 coords) //blurring depth
191
            {
192
                float d = 0.0;
193
                float kernel[9];
194
                vec2 offset[9];
195
                
196
                vec2 wh = vec2(texel.x, texel.y) * dbsize;
197
                
198
                offset[0] = vec2(-wh.x,-wh.y);
199
                offset[1] = vec2( 0.0, -wh.y);
200
                offset[2] = vec2( wh.x -wh.y);
201
                
202
                offset[3] = vec2(-wh.x,  0.0);
203
                offset[4] = vec2( 0.0,   0.0);
204
                offset[5] = vec2( wh.x,  0.0);
205
                
206
                offset[6] = vec2(-wh.x, wh.y);
207
                offset[7] = vec2( 0.0,  wh.y);
208
                offset[8] = vec2( wh.x, wh.y);
209
                
210
                kernel[0] = 1.0/16.0;   kernel[1] = 2.0/16.0;   kernel[2] = 1.0/16.0;
211
                kernel[3] = 2.0/16.0;   kernel[4] = 4.0/16.0;   kernel[5] = 2.0/16.0;
212
                kernel[6] = 1.0/16.0;   kernel[7] = 2.0/16.0;   kernel[8] = 1.0/16.0;
213
                
214
                
215
                for( int i=0; i<9; i++ )
216
                {
217
                    float tmp = texture2D(bgl_DepthTexture, coords + offset[i]).r;
218
                    d += tmp * kernel[i];
219
                }
220
                
221
                return d;
222
            }
223
                                                     
224
                                                     
225
            vec3 color(vec2 coords,float blur) //processing the sample
226
            {
227
                vec3 col = vec3(0.0);
228
                
229
                col.r = texture2D(bgl_RenderedTexture,coords + vec2(0.0,1.0)*texel*fringe*blur).r;
230
                col.g = texture2D(bgl_RenderedTexture,coords + vec2(-0.866,-0.5)*texel*fringe*blur).g;
231
                col.b = texture2D(bgl_RenderedTexture,coords + vec2(0.866,-0.5)*texel*fringe*blur).b;
232
                
233
                vec3 lumcoeff = vec3(0.299,0.587,0.114);
234
                float lum = dot(col.rgb, lumcoeff);
235
                float thresh = max((lum-threshold)*gain, 0.0);
236
                return col+mix(vec3(0.0),col,thresh*blur);
237
            }
238
                                                     
239
            vec2 rand(vec2 coord) //generating noise/pattern texture for dithering
240
            {
241
                float noiseX = ((fract(1.0-coord.s*(width/2.0))*0.25)+(fract(coord.t*(height/2.0))*0.75))*2.0-1.0;
242
                float noiseY = ((fract(1.0-coord.s*(width/2.0))*0.75)+(fract(coord.t*(height/2.0))*0.25))*2.0-1.0;
243
                
244
                if (noise)
245
                {
246
                    noiseX = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233))) * 43758.5453),0.0,1.0)*2.0-1.0;
247
                    noiseY = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233)*2.0)) * 43758.5453),0.0,1.0)*2.0-1.0;
248
                }
249
                return vec2(noiseX,noiseY);
250
            }
251
                                                     
252
            vec3 debugFocus(vec3 col, float blur, float depth)
253
            {
254
                float edge = 0.002*depth; //distance based edge smoothing
255
                float m = clamp(smoothstep(0.0,edge,blur),0.0,1.0);
256
                float e = clamp(smoothstep(1.0-edge,1.0,blur),0.0,1.0);
257
                
258
                col = mix(col,vec3(1.0,0.5,0.0),(1.0-m)*0.6);
259
                col = mix(col,vec3(0.0,0.5,1.0),((1.0-e)-(1.0-m))*0.2);
260
                
261
                return col;
262
            }
263
                                                     
264
            float linearize(float depth)
265
            {
266
                return -zfar * znear / (depth * (zfar - znear) - zfar);
267
            }
268

269
            float vignette()
270
            {
271
                float dist = distance(gl_TexCoord[3].xy, vec2(0.5,0.5));
272
                dist = smoothstep(vignout+(fstop/vignfade), vignin+(fstop/vignfade), dist);
273
                return clamp(dist,0.0,1.0);
274
            }
275
                                                     
276
            void main() 
277
            {
278
                //scene depth calculation
279
                
280
                float depth = linearize(texture2D(bgl_DepthTexture,gl_TexCoord[0].xy).x);
281
                
282
                if (depthblur)
283
                {
284
                    depth = linearize(bdepth(gl_TexCoord[0].xy));
285
                }
286
                
287
                //focal plane calculation
288
                
289
                float fDepth = focalDepth;
290
                
291
                if (autofocus)
292
                {
293
                    fDepth = linearize(texture2D(bgl_DepthTexture,focus).x);
294
                }
295
                
296
                //dof blur factor calculation
297
                
298
                float blur = 0.0;
299
                
300
                if (manualdof)
301
                {    
302
                    float a = depth-fDepth; //focal plane
303
                    float b = (a-fdofstart)/fdofdist; //far DoF
304
                    float c = (-a-ndofstart)/ndofdist; //near Dof
305
                    blur = (a>0.0)?b:c;
306
                }
307
                
308
                else
309
                {
310
                    float f = focalLength; //focal length in mm
311
                    float d = fDepth*1000.0; //focal plane in mm
312
                    float o = depth*1000.0; //depth in mm
313
                    
314
                    float a = (o*f)/(o-f); 
315
                    float b = (d*f)/(d-f); 
316
                    float c = (d-f)/(d*fstop*CoC); 
317
                    
318
                    blur = abs(a-b)*c;
319
                }
320
                
321
                blur = clamp(blur,0.0,1.0);
322
                
323
                // calculation of pattern for ditering
324
                
325
                vec2 noise = rand(gl_TexCoord[0].xy)*namount*blur;
326
                
327
                // getting blur x and y step factor
328
                
329
                float w = (1.0/width)*blur*maxblur+noise.x;
330
                float h = (1.0/height)*blur*maxblur+noise.y;
331
                
332
                // calculation of final color
333
                
334
                vec3 col = vec3(0.0);
335
                
336
                if(blur < 0.05) //some optimization thingy
337
                {
338
                    col = texture2D(bgl_RenderedTexture, gl_TexCoord[0].xy).rgb;
339
                }
340
                
341
                else
342
                {
343
                    col = texture2D(bgl_RenderedTexture, gl_TexCoord[0].xy).rgb;
344
                    float s = 1.0;
345
                    int ringsamples;
346
                    
347
                    for (int i = 1; i <= rings; i += 1)
348
                    {   
349
                        ringsamples = i * samples;
350
                        
351
                        for (int j = 0 ; j < ringsamples ; j += 1)   
352
                        {
353
                            float step = PI*2.0 / float(ringsamples);
354
                            float pw = (cos(float(j)*step)*float(i));
355
                            float ph = (sin(float(j)*step)*float(i));
356
                            float p = 1.0;
357
                            if (pentagon)
358
                            { 
359
                                p = penta(vec2(pw,ph));
360
                            }
361
                            col += color(gl_TexCoord[0].xy + vec2(pw*w,ph*h),blur)*mix(1.0,(float(i))/(float(rings)),bias)*p;  
362
                            s += 1.0*mix(1.0,(float(i))/(float(rings)),bias)*p;   
363
                        }
364
                    }
365
                    col /= s; //divide by sample count
366
                }
367
                
368
                if (showFocus)
369
                {
370
                    col = debugFocus(col, blur, depth);
371
                }
372
                
373
                if (vignetting)
374
                {
375
                    col *= vignette();
376
                }
377
                
378
                gl_FragColor.rgb = col;
379
                gl_FragColor.a = 1.0;
380
            }
381
        );
382
        
383
        shader.setupShaderFromSource(GL_FRAGMENT_SHADER, fragShaderSrc);
384
        shader.linkProgram();	
385
    }
386
    
387
    void DofAltPass::render(ofFbo& readFbo, ofFbo& writeFbo, ofTexture& depth)
388
    {
389
        writeFbo.begin();
390
        
391
        shader.begin();
392
        
393
        shader.setUniformTexture("bgl_RenderedTexture", readFbo.getTexture(), 0);
394
        shader.setUniformTexture("bgl_DepthTexture", depth, 1);
395
        shader.setUniform1f("bgl_RenderedTextureWidth", aspect.x);
396
        shader.setUniform1f("bgl_RenderedTextureHeight", aspect.y);
397
        
398
        shader.setUniform1f("focalDepth", focalDepth);  //focal distance value in meters, but you may use autofocus option below
399
        shader.setUniform1f("focalLength", focalLength); //focal length in mm
400
        shader.setUniform1f("fstop", fStop); //f-stop value
401
        shader.setUniform1f("showFocus", showFocus); //show debug focus point and focal range (red = focal point, green = focal range)
402

403
        texturedQuad(0, 0, writeFbo.getWidth(), writeFbo.getHeight());
404
        
405
        shader.end();
406
        writeFbo.end();
407
    }
408
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.