diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2015-09-24 18:24:20 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2015-09-24 18:24:20 +0300 |
commit | 27b3ea622f8bd313a8e2827dfec752bf2125566c (patch) | |
tree | f212e49d224ce8e1cfc3b17a64ae524711494391 /source/blender/gpu/shaders | |
parent | 372dff8d1dc7e24d4b2cd37de245588ecfce8bfa (diff) | |
parent | de80e687689032cb85179a1f7e89750573631d5d (diff) |
Merge remote-tracking branch 'origin/master' into cycles_camera_nodescycles_camera_nodes
Note: the branch currently crashes in blender_camera_nodes.cpp:
BL::NodeTree b_ntree = b_data.node_groups[nodes_tree_name];
The crash was introduced in:
cb7cf523e5c000609f32a382e2c0fcc57f635a42
Conflicts:
intern/cycles/SConscript
intern/cycles/blender/addon/__init__.py
intern/cycles/blender/addon/properties.py
intern/cycles/blender/blender_camera.cpp
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/camera.cpp
intern/cycles/render/camera.h
Diffstat (limited to 'source/blender/gpu/shaders')
16 files changed, 1060 insertions, 43 deletions
diff --git a/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl new file mode 100644 index 00000000000..a94c823f408 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl @@ -0,0 +1,32 @@ +!!ARBfp1.0 +PARAM dx = program.local[0]; +PARAM darkness = program.local[1]; +PARAM render = program.local[2]; +PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041}; +TEMP temp, shadow, flame, spec, value; +TEX temp, fragment.texcoord[0], texture[0], 3D; +TEX shadow, fragment.texcoord[0], texture[1], 3D; +TEX flame, fragment.texcoord[0], texture[2], 3D; +TEX spec, flame.r, texture[3], 1D; +# unpremultiply volume texture +RCP value.r, temp.a; +MUL temp.r, temp.r, value.r; +MUL temp.g, temp.g, value.r; +MUL temp.b, temp.b, value.r; +# calculate shading factor from density +MUL value.r, temp.a, darkness.a; +MUL value.r, value.r, dx.r; +MUL value.r, value.r, f.r; +EX2 value.r, -value.r; +# alpha +SUB temp.a, 1.0, value.r; +# shade colors +MUL temp.r, temp.r, shadow.r; +MUL temp.g, temp.g, shadow.r; +MUL temp.b, temp.b, shadow.r; +MUL temp.r, temp.r, value.r; +MUL temp.g, temp.g, value.r; +MUL temp.b, temp.b, value.r; +# for now this just replace smoke shading if rendering fire +CMP result.color, render.r, temp, spec; +END diff --git a/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl new file mode 100644 index 00000000000..04b171d24bd --- /dev/null +++ b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl @@ -0,0 +1,27 @@ +!!ARBfp1.0 +PARAM dx = program.local[0]; +PARAM darkness = program.local[1]; +PARAM render = program.local[2]; +PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01}; +TEMP temp, shadow, flame, spec, value; +TEX temp, fragment.texcoord[0], texture[0], 3D; +TEX shadow, fragment.texcoord[0], texture[1], 3D; +TEX flame, fragment.texcoord[0], texture[2], 3D; +TEX spec, flame.r, texture[3], 1D; +# calculate shading factor from density +MUL value.r, temp.a, darkness.a; +MUL value.r, value.r, dx.r; +MUL value.r, value.r, f.r; +EX2 temp, -value.r; +# alpha +SUB temp.a, 1.0, temp.r; +# shade colors +MUL temp.r, temp.r, shadow.r; +MUL temp.g, temp.g, shadow.r; +MUL temp.b, temp.b, shadow.r; +MUL temp.r, temp.r, darkness.r; +MUL temp.g, temp.g, darkness.g; +MUL temp.b, temp.b, darkness.b; +# for now this just replace smoke shading if rendering fire +CMP result.color, render.r, temp, spec; +END diff --git a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl new file mode 100644 index 00000000000..e04cd7d3306 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl @@ -0,0 +1,14 @@ +uniform sampler2D depthbuffer; +varying vec4 uvcoordsvar; + +void main(void) +{ + float depth = texture2D(depthbuffer, uvcoordsvar.xy).r; + + /* XRay background, discard */ + if (depth >= 1.0) { + discard; + } + + gl_FragDepth = depth; +} diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl new file mode 100644 index 00000000000..e9dab04de5d --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl @@ -0,0 +1,208 @@ +/* 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)); + /* using original color is not correct, but use that for now because alpha of + * blurred buffers uses CoC instead */ + gl_FragColor = vec4(color.rgb, color_orig.a); +} + + +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 +} diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl new file mode 100644 index 00000000000..e315d2fb97a --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl @@ -0,0 +1,166 @@ +/* amount of offset to move one pixel left-right. + * In second pass some dimensions are zero to control verical/horizontal convolution */ +uniform vec2 invrendertargetdim; + +uniform ivec2 rendertargetdim; + +/* color buffer */ +uniform sampler2D colorbuffer; +uniform sampler2D farbuffer; +uniform sampler2D nearbuffer; + +/* depth buffer */ +uniform sampler2D depthbuffer; + +uniform sampler2D cocbuffer; + +/* 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]; + +/* initial uv coordinate */ +varying vec2 uvcoord; + +/* coordinate used for calculating radius et al set in geometry shader */ +varying vec2 particlecoord; +varying vec4 color; + +/* downsampling coordinates */ +varying vec2 downsample1; +varying vec2 downsample2; +varying vec2 downsample3; +varying vec2 downsample4; + +#define M_PI 3.1415926535897932384626433832795 + +/* calculate 4 samples at once */ +vec4 calculate_coc(in vec4 zdepth) +{ + vec4 coc = dof_params.x * (vec4(dof_params.y) / zdepth - vec4(1.0)); + + /* multiply by 1.0 / sensor size to get the normalized size */ + return coc * dof_params.z; +} + +#define THRESHOLD 0.0 + +/* downsample the color buffer to half resolution */ +void downsample_pass() +{ + vec4 depth; + vec4 zdepth; + vec4 coc; + float far_coc, near_coc; + + /* custom downsampling. We need to be careful to sample nearest here to avoid leaks */ + vec4 color1 = texture2D(colorbuffer, downsample1); + vec4 color2 = texture2D(colorbuffer, downsample2); + vec4 color3 = texture2D(colorbuffer, downsample3); + vec4 color4 = texture2D(colorbuffer, downsample4); + + depth.r = texture2D(depthbuffer, downsample1).r; + depth.g = texture2D(depthbuffer, downsample2).r; + depth.b = texture2D(depthbuffer, downsample3).r; + depth.a = texture2D(depthbuffer, downsample4).r; + + zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth); + coc = calculate_coc(zdepth); + vec4 coc_far = -coc; + + /* now we need to write the near-far fields premultiplied by the coc */ + vec4 near_weights = vec4((coc.x >= THRESHOLD) ? 1.0 : 0.0, (coc.y >= THRESHOLD) ? 1.0 : 0.0, + (coc.z >= THRESHOLD) ? 1.0 : 0.0, (coc.w >= THRESHOLD) ? 1.0 : 0.0); + vec4 far_weights = vec4((coc_far.x >= THRESHOLD) ? 1.0 : 0.0, (coc_far.y >= THRESHOLD) ? 1.0 : 0.0, + (coc_far.z >= THRESHOLD) ? 1.0 : 0.0, (coc_far.w >= THRESHOLD) ? 1.0 : 0.0); + + near_coc = max(max(max(coc.x, coc.y), max(coc.z, coc.w)), 0.0); + far_coc = max(max(max(coc_far.x, coc_far.y), max(coc_far.z, coc_far.w)), 0.0); + + float norm_near = dot(near_weights, vec4(1.0)); + float norm_far = dot(far_weights, vec4(1.0)); + + /* now write output to weighted buffers. */ + gl_FragData[0] = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z + + color4 * near_weights.w; + gl_FragData[1] = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z + + color4 * far_weights.w; + + if (norm_near > 0.0) + gl_FragData[0] /= norm_near; + if (norm_far > 0.0) + gl_FragData[1] /= norm_far; + gl_FragData[2] = vec4(near_coc, far_coc, 0.0, 1.0); +} + +/* accumulate color in the near/far blur buffers */ +void accumulate_pass(void) { + float theta = atan(particlecoord.y, particlecoord.x); + float r; + + if (dof_params.w == 0.0) + r = 1.0; + else + r = cos(M_PI / dof_params.w) / (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI)))); + + if (dot(particlecoord, particlecoord) > r * r) + discard; + + gl_FragData[0] = color; +} +#define MERGE_THRESHOLD 4.0 + +/* combine the passes, */ +void final_pass(void) { + vec4 finalcolor; + float totalweight; + float depth = texture2D(depthbuffer, uvcoord).r; + + vec4 zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth)); + float coc_near = calculate_coc(zdepth).r; + float coc_far = max(-coc_near, 0.0); + coc_near = max(coc_near, 0.0); + + vec4 farcolor = texture2D(farbuffer, uvcoord); + float farweight = farcolor.a; + if (farweight > 0.0) + farcolor /= farweight; + vec4 nearcolor = texture2D(nearbuffer, uvcoord); + + vec4 srccolor = texture2D(colorbuffer, uvcoord); + + vec4 coc = texture2D(cocbuffer, uvcoord); + + float mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_far); + finalcolor = mix(srccolor, farcolor, mixfac); + + farweight = mix(1.0, farweight, mixfac); + + float nearweight = nearcolor.a; + if (nearweight > 0.0) { + nearcolor /= nearweight; + } + + if (coc_near > 1.0) { + nearweight = 1.0; + finalcolor = nearcolor; + } + else { + totalweight = nearweight + farweight; + finalcolor = mix(finalcolor, nearcolor, nearweight / totalweight); + } + + gl_FragData[0] = finalcolor; +} + +void main() +{ +#ifdef FIRST_PASS + downsample_pass(); +#elif defined(SECOND_PASS) + accumulate_pass(); +#elif defined(THIRD_PASS) + final_pass(); +#endif +} diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl new file mode 100644 index 00000000000..7918122a681 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl @@ -0,0 +1,50 @@ +uniform ivec2 rendertargetdim; +uniform sampler2D colorbuffer; + +uniform vec2 layerselection; + +uniform sampler2D cocbuffer; + +/* initial uv coordinate */ +varying in vec2 uvcoord[1]; +varying out vec2 particlecoord; +varying out vec4 color; + + +#define M_PI 3.1415926535897932384626433832795 + +void main(void) +{ + vec4 coc = texture2DLod(cocbuffer, uvcoord[0], 0.0); + + float offset_val = dot(coc.rg, layerselection); + if (offset_val < 1.0) + return; + + vec4 colortex = texture2DLod(colorbuffer, uvcoord[0], 0.0); + + /* find the area the pixel will cover and divide the color by it */ + float alpha = 1.0 / (offset_val * offset_val * M_PI); + colortex *= alpha; + colortex.a = alpha; + + vec2 offset_far = vec2(offset_val * 0.5) / vec2(rendertargetdim.x, rendertargetdim.y); + + gl_Position = gl_PositionIn[0] + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0); + color = colortex; + particlecoord = vec2(-1.0, -1.0); + EmitVertex(); + gl_Position = gl_PositionIn[0] + vec4(-offset_far.x, offset_far.y, 0.0, 0.0); + particlecoord = vec2(-1.0, 1.0); + color = colortex; + EmitVertex(); + gl_Position = gl_PositionIn[0] + vec4(offset_far.x, -offset_far.y, 0.0, 0.0); + particlecoord = vec2(1.0, -1.0); + color = colortex; + EmitVertex(); + gl_Position = gl_PositionIn[0] + vec4(offset_far.x, offset_far.y, 0.0, 0.0); + particlecoord = vec2(1.0, 1.0); + color = colortex; + EmitVertex(); + EndPrimitive(); +} diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl new file mode 100644 index 00000000000..09a0c75facc --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl @@ -0,0 +1,58 @@ +uniform vec2 invrendertargetdim; +uniform ivec2 rendertargetdim; +/* initial uv coordinate */ +varying vec2 uvcoord; + +/* coordinate used for calculating radius et al set in geometry shader */ +varying vec2 particlecoord; + +/* downsampling coordinates */ +varying vec2 downsample1; +varying vec2 downsample2; +varying vec2 downsample3; +varying vec2 downsample4; + +void vert_dof_downsample() +{ + /* gather pixels from neighbors. half dimensions means we offset half a pixel to + * get this right though it's possible we may lose a pixel at some point */ + downsample1 = gl_MultiTexCoord0.xy + vec2(-0.5, -0.5) * invrendertargetdim; + downsample2 = gl_MultiTexCoord0.xy + vec2(-0.5, 0.5) * invrendertargetdim; + downsample3 = gl_MultiTexCoord0.xy + vec2(0.5, 0.5) * invrendertargetdim; + downsample4 = gl_MultiTexCoord0.xy + vec2(0.5, -0.5) * invrendertargetdim; + + gl_Position = gl_Vertex; +} + +/* geometry shading pass, calculate a texture coordinate based on the indexed id */ +void vert_dof_coc_scatter_pass() +{ + vec2 pixel = vec2(rendertargetdim.x, rendertargetdim.y); + /* some math to get the target pixel */ + int row = gl_InstanceID / rendertargetdim.x; + int column = gl_InstanceID % rendertargetdim.x; + uvcoord = (vec2(column, row) + vec2(0.5)) / pixel; + + vec2 pos = uvcoord * 2.0 - vec2(1.0); + gl_Position = vec4(pos.x, pos.y, 0.0, 1.0); + +// uvcoord = vec2(0.5, 0.5); +// gl_Position = vec4(0.0, 0.0, 0.0, 1.0); +} + +void vert_dof_final() +{ + uvcoord = gl_MultiTexCoord0.xy; + gl_Position = gl_Vertex; +} + +void main() +{ +#if defined(FIRST_PASS) + vert_dof_downsample(); +#elif defined(SECOND_PASS) + vert_dof_coc_scatter_pass(); +#else + vert_dof_final(); +#endif +}
\ No newline at end of file diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl new file mode 100644 index 00000000000..a2ef990c4e8 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl @@ -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 +} + diff --git a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl new file mode 100644 index 00000000000..1dc49b52be1 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl @@ -0,0 +1,39 @@ +/* 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 diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl new file mode 100644 index 00000000000..494a74dcdf8 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl @@ -0,0 +1,94 @@ +// 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 vec3 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]; + +vec3 calculate_view_space_normal(in vec3 viewposition) +{ + vec3 normal = cross(normalize(dFdx(viewposition)), + ssao_params.w * normalize(dFdy(viewposition))); + normalize(normal); + return normal; +} + +float calculate_ssao_factor(float depth) +{ + /* take the normalized ray direction here */ + vec2 rotX = texture2D(jitter_tex, uvcoordsvar.xy * ssao_sample_params.yz).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; + + if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0) + continue; + + 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 scene_col = texture2D(colorbuffer, uvcoordsvar.xy); + vec3 final_color = mix(scene_col.rgb, ssao_color.rgb, calculate_ssao_factor(depth)); + gl_FragColor = vec4(final_color.rgb, scene_col.a); +} diff --git a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl new file mode 100644 index 00000000000..5194e414520 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl @@ -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; +} diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl new file mode 100644 index 00000000000..a0ae96a1f72 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl @@ -0,0 +1,100 @@ +uniform int PrimitiveIdBase; +uniform int osd_active_uv_offset; + +varying vec3 varnormal; +varying vec3 varposition; + +in block { + VertexData v; +} inpt[4]; + +uniform bool osd_flat_shading; +uniform int osd_fvar_count; + +#define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) \ + { \ + vec2 v[4]; \ + int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \ + for (int i = 0; i < 4; ++i) { \ + int index = (primOffset + i) * osd_fvar_count + fvarOffset; \ + v[i] = vec2(texelFetch(FVarDataBuffer, index).s, \ + texelFetch(FVarDataBuffer, index + 1).s); \ + } \ + result = mix(mix(v[0], v[1], tessCoord.s), \ + mix(v[3], v[2], tessCoord.s), \ + tessCoord.t); \ + } + +uniform samplerBuffer FVarDataBuffer; + +out block { + VertexData v; +} outpt; + +void set_mtface_vertex_attrs(vec2 st); + +void emit_flat(int index, vec3 normal) +{ + outpt.v.position = inpt[index].v.position; + outpt.v.normal = normal; + + /* Compatibility */ + varnormal = outpt.v.normal; + varposition = outpt.v.position.xyz; + + /* TODO(sergey): Only uniform subdivisions atm. */ + vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1)); + vec2 st = quadst[index]; + + INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st); + + set_mtface_vertex_attrs(st); + + gl_Position = gl_ProjectionMatrix * inpt[index].v.position; + EmitVertex(); +} + +void emit_smooth(int index) +{ + outpt.v.position = inpt[index].v.position; + outpt.v.normal = inpt[index].v.normal; + + /* Compatibility */ + varnormal = outpt.v.normal; + varposition = outpt.v.position.xyz; + + /* TODO(sergey): Only uniform subdivisions atm. */ + vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1)); + vec2 st = quadst[index]; + + INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st); + + set_mtface_vertex_attrs(st); + + gl_Position = gl_ProjectionMatrix * inpt[index].v.position; + EmitVertex(); +} + +void main() +{ + gl_PrimitiveID = gl_PrimitiveIDIn; + + if (osd_flat_shading) { + vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz; + vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz; + vec3 flat_normal = normalize(cross(B, A)); + emit_flat(0, flat_normal); + emit_flat(1, flat_normal); + emit_flat(3, flat_normal); + emit_flat(2, flat_normal); + } + else { + emit_smooth(0); + emit_smooth(1); + emit_smooth(3); + emit_smooth(2); + } + EndPrimitive(); +} + +void set_mtface_vertex_attrs(vec2 st) { diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 3ba36c11311..311fcb8ead2 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -149,10 +149,23 @@ void geom(vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 att uv_attribute(attuv, uv); normal = -normalize(nor); /* blender render normal is negated */ vcol_attribute(attvcol, vcol); + srgb_to_linearrgb(vcol, vcol); vcol_alpha = attvcol.a; frontback = (gl_FrontFacing)? 1.0: 0.0; } +void particle_info(vec4 sprops, vec3 loc, vec3 vel, vec3 avel, out float index, out float age, out float life_time, out vec3 location, out float size, out vec3 velocity, out vec3 angular_velocity) +{ + index = sprops.x; + age = sprops.y; + life_time = sprops.z; + size = sprops.w; + + location = loc; + velocity = vel; + angular_velocity = avel; +} + void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec) { outvec = (mat * vec4(vec, 1.0)).xyz; @@ -169,9 +182,9 @@ void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) outview = normalize(co); } -void lamp(vec4 col, vec3 lv, float dist, vec3 shadow, float visifac, out vec4 outcol, out vec3 outlv, out float outdist, out vec4 outshadow, out float outvisifac) +void lamp(vec4 col, float energy, vec3 lv, float dist, vec3 shadow, float visifac, out vec4 outcol, out vec3 outlv, out float outdist, out vec4 outshadow, out float outvisifac) { - outcol = col; + outcol = col * energy; outlv = lv; outdist = dist; outshadow = vec4(shadow, 1.0); @@ -297,6 +310,10 @@ void math_modulo(float val1, float val2, out float outval) outval = 0.0; else outval = mod(val1, val2); + + /* change sign to match C convention, mod in GLSL will take absolute for negative numbers, + * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */ + outval = (val1 > 0.0) ? outval : -outval; } void math_abs(float val1, out float outval) @@ -338,6 +355,7 @@ void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval) { outvec = cross(v1, v2); outval = length(outvec); + outvec /= outval; } void vec_math_normalize(vec3 v, out vec3 outvec, out float outval) @@ -357,6 +375,12 @@ void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot) outdot = -dot(dir, nor); } +void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot) +{ + outnor = normalize(nor); + outdot = dot(normalize(dir), nor); +} + void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec) { outvec.x = texture2D(curvemap, vec2((vec.x + 1.0)*0.5, 0.0)).x; @@ -687,22 +711,7 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol) { fac = clamp(fac, 0.0, 1.0); - outcol = col1; - - if(col2.r > 0.5) - outcol.r= col1.r + fac*(2.0*(col2.r - 0.5)); - else - outcol.r= col1.r + fac*(2.0*(col2.r) - 1.0); - - if(col2.g > 0.5) - outcol.g= col1.g + fac*(2.0*(col2.g - 0.5)); - else - outcol.g= col1.g + fac*(2.0*(col2.g) - 1.0); - - if(col2.b > 0.5) - outcol.b= col1.b + fac*(2.0*(col2.b - 0.5)); - else - outcol.b= col1.b + fac*(2.0*(col2.b) - 1.0); + outcol = col1 + fac*(2.0*(col2 - vec4(0.5))); } void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha) @@ -722,6 +731,16 @@ void invert(float fac, vec4 col, out vec4 outcol) outcol.w = col.w; } +void clamp_vec3(vec3 vec, vec3 min, vec3 max, out vec3 out_vec) +{ + out_vec = clamp(vec, min, max); +} + +void clamp_val(float value, float min, float max, out float out_value) +{ + out_value = clamp(value, min, max); +} + void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol) { vec4 hsv; @@ -1507,9 +1526,9 @@ void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal) outnormal = normalize((viewmat*vec4(texnormal, 0.0)).xyz); } -void mtex_nspace_object(mat4 viewmat, mat4 obmat, vec3 texnormal, out vec3 outnormal) +void mtex_nspace_object(vec3 texnormal, out vec3 outnormal) { - outnormal = normalize((viewmat*(obmat*vec4(texnormal, 0.0))).xyz); + outnormal = normalize(gl_NormalMatrix * texnormal); } void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal) @@ -1925,6 +1944,17 @@ void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol) outcol = t*lampcol*speccol; } +void alpha_spec_correction(vec3 spec, float spectra, float alpha, out float outalpha) +{ + if (spectra > 0.0) { + float t = clamp(max(max(spec.r, spec.g), spec.b) * spectra, 0.0, 1.0); + outalpha = (1.0 - t) * alpha + t; + } + else { + outalpha = alpha; + } +} + void shade_add(vec4 col1, vec4 col2, out vec4 outcol) { outcol = col1 + col2; @@ -1960,6 +1990,11 @@ void shade_mul_value(float fac, vec4 col, out vec4 outcol) outcol = col*fac; } +void shade_mul_value_v3(float fac, vec3 col, out vec3 outcol) +{ + outcol = col*fac; +} + void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol) { outcol = vec4(col.rgb*obcol.rgb, col.a); @@ -2077,18 +2112,23 @@ void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outco outcol = linfac*(1.0 - exp(col*logfac)); } -void shade_mist_factor(vec3 co, float miststa, float mistdist, float misttype, float misi, out float outfac) +void shade_mist_factor(vec3 co, float enable, float miststa, float mistdist, float misttype, float misi, out float outfac) { - float fac, zcor; + if(enable == 1.0) { + float fac, zcor; - zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2]; - - fac = clamp((zcor-miststa)/mistdist, 0.0, 1.0); - if(misttype == 0.0) fac *= fac; - else if(misttype == 1.0); - else fac = sqrt(fac); + zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2]; + + fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0); + if(misttype == 0.0) fac *= fac; + else if(misttype == 1.0); + else fac = sqrt(fac); - outfac = 1.0 - (1.0-fac)*(1.0-misi); + outfac = 1.0 - (1.0 - fac) * (1.0 - misi); + } + else { + outfac = 0.0; + } } void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol) @@ -2223,6 +2263,16 @@ void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv result = color; } +void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out vec4 result) +{ + node_bsdf_diffuse(color, 0.0, N, result); +} + +void node_ambient_occlusion(vec4 color, out vec4 result) +{ + result = color; +} + /* emission */ void node_emission(vec4 color, float strength, vec3 N, out vec4 result) @@ -2230,6 +2280,22 @@ void node_emission(vec4 color, float strength, vec3 N, out vec4 result) result = color*strength; } +/* background */ + +void background_transform_to_world(vec3 viewvec, out vec3 worldvec) +{ + vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + worldvec = (gl_ModelViewMatrixInverse * co).xyz; +} + +void node_background(vec4 color, float strength, vec3 N, out vec4 result) +{ + result = color*strength; +} + /* closures */ void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader) @@ -2259,10 +2325,12 @@ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float { /* fresnel */ float eta = max(1.0 - blend, 0.00001); - fresnel = fresnel_dielectric(normalize(I), N, (gl_FrontFacing)? 1.0/eta : eta ); + vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(I): vec3(0.0, 0.0, -1.0); + + fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing)? 1.0/eta : eta ); /* facing */ - facing = abs(dot(normalize(I), N)); + facing = abs(dot(I_view, N)); if(blend != 0.5) { blend = clamp(blend, 0.0, 0.99999); blend = (blend < 0.5)? 2.0*blend: 0.5/(1.0 - blend); @@ -2302,7 +2370,7 @@ void node_uvmap(vec3 attr_uv, out vec3 outvec) void node_geometry(vec3 I, vec3 N, mat4 toworld, out vec3 position, out vec3 normal, out vec3 tangent, out vec3 true_normal, out vec3 incoming, out vec3 parametric, - out float backfacing) + out float backfacing, out float pointiness) { position = (toworld*vec4(I, 1.0)).xyz; normal = (toworld*vec4(N, 0.0)).xyz; @@ -2315,20 +2383,21 @@ void node_geometry(vec3 I, vec3 N, mat4 toworld, parametric = vec3(0.0); backfacing = (gl_FrontFacing)? 0.0: 1.0; + pointiness = 0.0; } -void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, +void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac, vec3 attr_orco, vec3 attr_uv, out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, out vec3 camera, out vec3 window, out vec3 reflection) { - generated = mtex_2d_mapping(attr_orco); + generated = attr_orco * 0.5 + vec3(0.5); normal = normalize((obinvmat*(viewinvmat*vec4(N, 0.0))).xyz); uv = attr_uv; object = (obinvmat*(viewinvmat*vec4(I, 1.0))).xyz; - camera = I; + camera = vec3(I.xy, -I.z); vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0); - window = mtex_2d_mapping(projvec.xyz/projvec.w); + window = vec3(mtex_2d_mapping(projvec.xyz/projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); vec3 shade_I; shade_view(I, shade_I); @@ -2336,6 +2405,32 @@ void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, reflection = (viewinvmat*vec4(view_reflection, 0.0)).xyz; } +void node_tex_coord_background(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac, + vec3 attr_orco, vec3 attr_uv, + out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, + out vec3 camera, out vec3 window, out vec3 reflection) +{ + vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + + co = normalize(co); + vec3 coords = (gl_ModelViewMatrixInverse * co).xyz; + + generated = coords; + normal = -coords; + uv = vec3(attr_uv.xy, 0.0); + object = coords; + + camera = vec3(co.xy, -co.z); + window = (gl_ProjectionMatrix[3][3] == 0.0) ? + vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) : + vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0); + + reflection = -coords; +} + /* textures */ void node_tex_gradient(vec3 co, out vec4 color, out float fac) @@ -2362,17 +2457,34 @@ void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac) fac = 1.0; } -void node_tex_environment(vec3 co, sampler2D ima, out vec4 color) +void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color) +{ + vec3 nco = normalize(co); + float u = -atan(nco.y, nco.x)/(2.0*M_PI) + 0.5; + float v = atan(nco.z, hypot(nco.x, nco.y))/M_PI + 0.5; + + color = texture2D(ima, vec2(u, v)); +} + +void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color) { - float u = (atan(co.y, co.x) + M_PI)/(2.0*M_PI); - float v = atan(co.z, hypot(co.x, co.y))/M_PI + 0.5; + vec3 nco = normalize(co); + + nco.y -= 1.0; + + float div = 2.0*sqrt(max(-0.5*nco.y, 0.0)); + if(div > 0.0) + nco /= div; + + float u = 0.5*(nco.x + 1.0); + float v = 0.5*(nco.z + 1.0); color = texture2D(ima, vec2(u, v)); } void node_tex_environment_empty(vec3 co, out vec4 color) { - color = vec4(0.0); + color = vec4(1.0, 0.0, 1.0, 1.0); } void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha) @@ -2480,6 +2592,11 @@ void node_output_material(vec4 surface, vec4 volume, float displacement, out vec result = surface; } +void node_output_world(vec4 surface, vec4 volume, out vec4 result) +{ + result = surface; +} + /* ********************** matcap style render ******************** */ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result) @@ -2487,6 +2604,7 @@ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out v vec3 normal; vec2 tex; +#ifndef USE_OPENSUBDIV /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors * between shader stages and we want the full range of the normal */ normal = vec3(2.0, 2.0, 2.0) * vec3(N.x, N.y, N.z) - vec3(1.0, 1.0, 1.0); @@ -2494,6 +2612,10 @@ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out v normal.z = 0.0; } normal = normalize(normal); +#else + normal = inpt.v.normal; + mask = vec4(1.0, 1.0, 1.0, 1.0); +#endif tex.x = 0.5 + 0.49 * normal.x; tex.y = 0.5 + 0.49 * normal.y; diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl index 978b6db1b9a..5f406c959f1 100644 --- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl @@ -10,7 +10,7 @@ void main() color += texture2D( textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125; color += texture2D( textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y ) ) * 0.234375; color += texture2D( textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y ) ) * 0.09375; - color += texture2D( textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, -3.0 * ScaleU.y ) ) * 0.015625; + color += texture2D( textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y ) ) * 0.015625; gl_FragColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl index b5d8dcc0f35..7e332706695 100644 --- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl @@ -1,3 +1,11 @@ +#ifdef USE_OPENSUBDIV +in vec3 normal; +in vec4 position; + +out block { + VertexData v; +} outpt; +#endif varying vec3 varposition; varying vec3 varnormal; @@ -8,10 +16,15 @@ varying float gl_ClipDistance[6]; void main() { - vec4 co = gl_ModelViewMatrix * gl_Vertex; +#ifndef USE_OPENSUBDIV + vec4 position = gl_Vertex; + vec3 normal = gl_Normal; +#endif + + vec4 co = gl_ModelViewMatrix * position; varposition = co.xyz; - varnormal = normalize(gl_NormalMatrix * gl_Normal); + varnormal = normalize(gl_NormalMatrix * normal); gl_Position = gl_ProjectionMatrix * co; #ifdef CLIP_WORKAROUND @@ -24,3 +37,7 @@ void main() gl_ClipVertex = co; #endif +#ifdef USE_OPENSUBDIV + outpt.v.position = co; + outpt.v.normal = varnormal; +#endif diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl new file mode 100644 index 00000000000..9dbcaeb7a32 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl @@ -0,0 +1,13 @@ + +varying vec3 varposition; +varying vec3 varnormal; + +void main() +{ + /* position does not need to be transformed, we already have it */ + gl_Position = gl_Vertex; + + varposition = gl_Vertex.xyz; + + varnormal = normalize(-varposition); + |