diff options
author | Dave Parks <davep@lindenlab.com> | 2010-11-24 03:36:41 -0600 |
---|---|---|
committer | Dave Parks <davep@lindenlab.com> | 2010-11-24 03:36:41 -0600 |
commit | 894dd833f7351ead340047bd5d6f9950a5cecbeb (patch) | |
tree | 10e6539c2d3cdafc2b74238063d0293d774e92c5 /indra | |
parent | 2915715ec4a9bb7978c4a0db0afc26b73ab8b2fb (diff) |
Depth of Field whenever "Lighting and Shadows" is enabled and global-illumination is not (experimental).
Diffstat (limited to 'indra')
-rwxr-xr-x | indra/newview/app_settings/settings.xml | 40 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl | 172 | ||||
-rw-r--r-- | indra/newview/lldrawpoolalpha.cpp | 45 | ||||
-rw-r--r-- | indra/newview/llviewerwindow.cpp | 20 | ||||
-rw-r--r-- | indra/newview/pipeline.cpp | 60 |
5 files changed, 282 insertions, 55 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5cc8c34cd5..4efb8edd63 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1332,7 +1332,45 @@ <key>Value</key> <integer>0</integer> </map> - <key>CertStore</key> + + <key>CameraFNumber</key> + <map> + <key>Comment</key> + <string>Camera f-number value for DoF effect</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>2.8</real> + </map> + + <key>CameraFocalLength</key> + <map> + <key>Comment</key> + <string>Camera focal length for DoF effect (in millimeters)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>50</real> + </map> + + <key>CameraCoC</key> + <map> + <key>Comment</key> + <string>Camera circle of confusion for DoF effect (in millimeters)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.5</real> + </map> + + + <key>CertStore</key> <map> <key>Comment</key> <string>Specifies the Certificate Store for certificate trust verification</string> diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl index 03c2e63fb1..eec44d9d42 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -17,6 +17,8 @@ uniform sampler2D bloomMap; uniform float depth_cutoff; uniform float norm_cutoff; +uniform float near_focal_distance; +uniform float far_focal_distance; uniform mat4 inv_proj; uniform vec2 screen_res; @@ -32,55 +34,149 @@ float getDepth(vec2 pos_screen) return p.z/p.w; } +void dofSample(inout vec4 diff, inout float w, float fd, float x, float y) +{ + vec2 tc = vary_fragcoord.xy+vec2(x,y); + float d = getDepth(tc); + + if (d < fd) + { + diff += texture2DRect(diffuseRect, tc); + w += 1.0; + } +} + +void dofSampleNear(inout vec4 diff, inout float w, float x, float y) +{ + vec2 tc = vary_fragcoord.xy+vec2(x,y); + + diff += texture2DRect(diffuseRect, tc); + w += 1.0; +} + void main() { vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm - float depth = getDepth(vary_fragcoord.xy); + vec2 tc = vary_fragcoord.xy; float sc = 0.75; - vec2 de; - de.x = (depth-getDepth(tc+vec2(sc, sc))) + (depth-getDepth(tc+vec2(-sc, -sc))); - de.y = (depth-getDepth(tc+vec2(-sc, sc))) + (depth-getDepth(tc+vec2(sc, -sc))); - de /= depth; - de *= de; - de = step(depth_cutoff, de); - - vec2 ne; - vec3 nexnorm = texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb; - nexnorm = vec3((nexnorm.xy-0.5)*2.0,nexnorm.z); // unpack norm - ne.x = dot(nexnorm, norm); - vec3 neynorm = texture2DRect(normalMap, tc+vec2(sc,sc)).rgb; - neynorm = vec3((neynorm.xy-0.5)*2.0,neynorm.z); // unpack norm - ne.y = dot(neynorm, norm); - - ne = 1.0-ne; - - ne = step(norm_cutoff, ne); - - float edge_weight = clamp(dot(de,de)+dot(ne,ne), 0.0, 1.0); - //edge_weight *= 0.0; - - vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res); + float depth[5]; + depth[0] = getDepth(tc); + vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); - diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(1,1))*edge_weight; - diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(-1,-1))*edge_weight; - diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(-1,1))*edge_weight; - diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(1,-1))*edge_weight; - diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(-1,0))*edge_weight; - diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(1,0))*edge_weight; - diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(0,1))*edge_weight; - diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(0,-1))*edge_weight; - - diff /= 1.0+edge_weight*8.0; + bool do_aa = true; - vec4 blur = texture2DRect(edgeMap, vary_fragcoord.xy); - - //gl_FragColor = vec4(edge_weight,edge_weight,edge_weight, 1.0); + if (depth[0] < far_focal_distance) + { //pixel is behind far focal plane + float w = 1.0; + + float fd = far_focal_distance; + float sc = clamp(depth[0]/fd, 0.0, -8.0/fd); + sc = min(sc, 8.0); + + //fd = depth[0]*0.5; + + while (sc > 1.0) + { + do_aa = false; + dofSample(diff,w, fd, sc,sc); + dofSample(diff,w, fd, -sc,sc); + dofSample(diff,w, fd, sc,-sc); + dofSample(diff,w, fd, -sc,-sc); + + sc -= 0.5; + float sc2 = sc*1.414; + dofSample(diff,w, fd, 0,sc2); + dofSample(diff,w, fd, 0,-sc2); + dofSample(diff,w, fd, -sc2,0); + dofSample(diff,w, fd, sc2,0); + sc -= 0.5; + } + diff /= w; + } + else + { + float fd = near_focal_distance; + + if (depth[0] > fd) + { //pixel is in front of near focal plane + //diff.r = 1.0; + float w = 1.0; + float sc = depth[0] - fd; + sc = min(-sc/fd*16.0, 8.0); + + fd = depth[0]; + while (sc > 1.0) + { + do_aa = false; + dofSampleNear(diff,w, sc,sc); + dofSampleNear(diff,w, -sc,sc); + dofSampleNear(diff,w, sc,-sc); + dofSampleNear(diff,w, -sc,-sc); + + sc -= 0.5; + float sc2 = sc*1.414; + dofSampleNear(diff,w, 0,sc2); + dofSampleNear(diff,w, 0,-sc2); + dofSampleNear(diff,w, -sc2,0); + dofSampleNear(diff,w, sc2,0); + sc -= 0.5; + } + diff /= w; + } + + if (do_aa) + { + depth[1] = getDepth(tc+vec2(sc,sc)); + depth[2] = getDepth(tc+vec2(-sc,-sc)); + depth[3] = getDepth(tc+vec2(-sc,sc)); + depth[4] = getDepth(tc+vec2(sc, -sc)); + + + vec2 de; + de.x = (depth[0]-depth[1]) + (depth[0]-depth[2]); + de.y = (depth[0]-depth[3]) + (depth[0]-depth[4]); + de /= depth[0]; + de *= de; + de = step(depth_cutoff, de); + + vec2 ne; + vec3 nexnorm = texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb; + nexnorm = vec3((nexnorm.xy-0.5)*2.0,nexnorm.z); // unpack norm + ne.x = dot(nexnorm, norm); + vec3 neynorm = texture2DRect(normalMap, tc+vec2(sc,sc)).rgb; + neynorm = vec3((neynorm.xy-0.5)*2.0,neynorm.z); // unpack norm + ne.y = dot(neynorm, norm); + + ne = 1.0-ne; + + ne = step(norm_cutoff, ne); + + float edge_weight = clamp(dot(de,de)+dot(ne,ne), 0.0, 1.0); + //edge_weight *= 0.0; + + //diff.r = edge_weight; + + if (edge_weight > 0.0) + { + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(1,1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(-1,-1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(-1,1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(1,-1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(-1,0))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(1,0))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(0,1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(0,-1))*edge_weight; + diff /= 1.0+edge_weight*8.0; + } + } + } + + vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res); gl_FragColor = diff + bloom; - //gl_FragColor.r = edge_weight; } diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index a2428d2de0..2519d0297c 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -103,16 +103,29 @@ void LLDrawPoolAlpha::renderDeferred(S32 pass) S32 LLDrawPoolAlpha::getNumPostDeferredPasses() { - return 1; + return 2; } void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) { LLFastTimer t(FTM_RENDER_ALPHA); - simple_shader = &gDeferredAlphaProgram; - fullbright_shader = &gDeferredFullbrightProgram; - + if (pass == 0) + { + simple_shader = &gDeferredAlphaProgram; + fullbright_shader = &gDeferredFullbrightProgram; + } + else + { + //update depth buffer sampler + gPipeline.mScreen.flush(); + gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), + 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + gPipeline.mDeferredDepth.bindTarget(); + simple_shader = NULL; + fullbright_shader = NULL; + } + deferred_render = TRUE; if (mVertexShaderLevel > 0) { @@ -124,6 +137,8 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) { + gPipeline.mDeferredDepth.flush(); + gPipeline.mScreen.bindTarget(); deferred_render = FALSE; endRenderPass(pass); } @@ -174,7 +189,14 @@ void LLDrawPoolAlpha::render(S32 pass) LLGLSPipelineAlpha gls_pipeline_alpha; - gGL.setColorMask(true, true); + if (deferred_render && pass == 1) + { //depth only + gGL.setColorMask(false, false); + } + else + { + gGL.setColorMask(true, true); + } if (LLPipeline::sAutoMaskAlphaNonDeferred && !deferred_render) { @@ -206,7 +228,13 @@ void LLDrawPoolAlpha::render(S32 pass) gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } - LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy ? GL_TRUE : GL_FALSE); + LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy || + (deferred_render && pass == 1) ? GL_TRUE : GL_FALSE); + + if (deferred_render && pass == 1) + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); + } mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } @@ -218,6 +246,11 @@ void LLDrawPoolAlpha::render(S32 pass) gGL.setColorMask(true, false); + if (deferred_render && pass == 1) + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } + if (deferred_render && current_shader != NULL) { gPipeline.unbindDeferredShader(*current_shader); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 972c9c255e..20d9f49a3e 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3549,6 +3549,8 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de LLVector3 mouse_world_start = mouse_point_global; LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth; + //gDebugRaycastIntersection = mouse_world_end; + if (start) { *start = mouse_world_start; @@ -3570,8 +3572,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de { found = this_object; } - } - + } else // is a world object { if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, pick_transparent, @@ -3579,21 +3580,22 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de { found = this_object; } - } - } - + } + } else // check ALL objects - { + { found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, pick_transparent, face_hit, intersection, uv, normal, binormal); if (!found) // if not found in HUD, look in world: - - { + { found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end, pick_transparent, face_hit, intersection, uv, normal, binormal); + if (found) + { + gDebugRaycastIntersection = *intersection; } - + } } return found; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4007d9d8f3..a189d17dc8 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6253,14 +6253,71 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { shader = &gDeferredGIFinalProgram; } - + LLGLDisable blend(GL_BLEND); bindDeferredShader(*shader); + + //depth of field focal plane calculations + + F32 subject_distance = 16.f; + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + //flycam mode, use mouse cursor as focus point + LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); + subject_distance = (eye-gDebugRaycastIntersection).magVec(); + } + else + { + LLViewerObject* obj = gAgentCamera.getFocusObject(); + if (obj) + { + LLVector3 focus = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal()); + LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); + subject_distance = (focus-eye).magVec(); + } + } + + //convert to mm + subject_distance *= 1000.f; + F32 fnumber = gSavedSettings.getF32("CameraFNumber"); + F32 focal_length = gSavedSettings.getF32("CameraFocalLength"); + F32 coc = gSavedSettings.getF32("CameraCoC"); + + + F32 hyperfocal_distance = (focal_length*focal_length)/(fnumber*coc); + + subject_distance = llmin(hyperfocal_distance, subject_distance); + + //adjust focal length for subject distance + focal_length = llmax(focal_length, 1.f/(1.f/focal_length - 1.f/subject_distance)); + + //adjust focal length for zoom + F32 fov = LLViewerCamera::getInstance()->getView(); + F32 default_fov = LLViewerCamera::getInstance()->getDefaultFOV(); + focal_length *= default_fov/fov; + + F32 near_focal_distance = hyperfocal_distance*subject_distance/(hyperfocal_distance+subject_distance); + + //beyond far clip plane is effectively infinity + F32 far_focal_distance = 4096.f; + + if (subject_distance < hyperfocal_distance) + { + far_focal_distance = hyperfocal_distance*subject_distance/(hyperfocal_distance-subject_distance); + far_focal_distance /= 1000.f; + } + + near_focal_distance /= 1000.f; + + shader->uniform1f("far_focal_distance", -far_focal_distance); + shader->uniform1f("near_focal_distance", -near_focal_distance); + S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { mScreen.bindTexture(0, channel); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } gGL.begin(LLRender::TRIANGLE_STRIP); @@ -6753,6 +6810,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen shader.uniform2f("proj_shadow_res", mShadow[4].getWidth(), mShadow[4].getHeight()); shader.uniform1f("depth_cutoff", gSavedSettings.getF32("RenderEdgeDepthCutoff")); shader.uniform1f("norm_cutoff", gSavedSettings.getF32("RenderEdgeNormCutoff")); + if (shader.getUniformLocation("norm_mat") >= 0) { |