void CLockBox9::on_add_node_child(StateDataNode* parent, StateDataNode* child) { if(child->get_id().name == NAME_LOCKBOX) { /** @todo Perhaps it's necessary to copy volume DATA to lock DATA, depending on the flags. Without this, if application only modifies a region of lock DATA the contents of the surface DATA corresponding to a non modified regions of lock DATA are overwritten with zeroes. */ // Calculate size of DATA node and resize it D3DFORMAT format; child->get_parent()->get_child(StateId(NAME_FORMAT))->read_data(&format); UINT left, right, top, bottom, front, back; child->get_child(StateId(NAME_LEFT))->read_data(&left); child->get_child(StateId(NAME_RIGHT))->read_data(&right); child->get_child(StateId(NAME_TOP))->read_data(&top); child->get_child(StateId(NAME_BOTTOM))->read_data(&bottom); child->get_child(StateId(NAME_TOP))->read_data(&front); child->get_child(StateId(NAME_BOTTOM))->read_data(&back); UINT width = right - left; UINT height = bottom - top; UINT depth = back - front; // Change units for compressed formats /// @note Depth is not affected if(is_compressed(format)) { width = width / 4 + (((width % 4) == 0) ? 0 : 1); height = height / 4 + (((height % 4) == 0) ? 0 : 1); } UINT size = depth * width * height * texel_size(format); child->get_child(StateId(NAME_DATA))->set_data_size(size); D3D_DEBUG( cout << "CLOCKBOX9: Resizing SLOCKBOX DATA to " << (int)size << endl; )
// 生成DOF的模糊MASK void ATOM_DOFEffect::genDofBlurMask (ATOM_RenderDevice *device) { _material->setActiveEffect ("GenDofBlurMask"); ATOM_Vector4f texel_size(1.0f/_blurTexs[0]->getWidth(),1.0f/_blurTexs[0]->getHeight(),0,0); _material->getParameterTable()->setVector("texelSize",texel_size); // 焦距参数 float focus_range_far = _focusRange * 0.5f; float focus_range_near = -_focusRange * 0.5f; ATOM_Vector4f vDofParamsFocus0; vDofParamsFocus0.x = 1.0f / (focus_range_far + 1e-6f); vDofParamsFocus0.y = -_focusDistance / (focus_range_far + 1e-6f); vDofParamsFocus0.z = 1.0f / (focus_range_near + 1e-6f); vDofParamsFocus0.w = -_focusDistance / (focus_range_near + 1e-6f); _material->getParameterTable()->setVector("vDofParamsFocus0", vDofParamsFocus0); ATOM_Vector4f vDofParamsFocus1; vDofParamsFocus1.x = _dofMinz; vDofParamsFocus1.y = _dofMinzScale; vDofParamsFocus1.z = _dofMinZBlendMult; vDofParamsFocus1.w = _blurCoefficient; _material->getParameterTable()->setVector("vDofParamsFocus1", vDofParamsFocus1); _material->getParameterTable()->setFloat("focusPower", _focusPower); //_material->getParameterTable()->setTexture ("tex0", _source.get()); #if USE_OPTIMIZATION device->setRenderTarget (0, _source.get()); // 优化 使用源RT作为渲染目标,只写ALPHA device->setViewport (0, ATOM_Rect2Di(0, 0,_source->getWidth(), _source->getHeight())); drawTexturedFullscreenQuad (device, _material.get(), _source->getWidth(), _source->getHeight()); #else device->setRenderTarget (0, _dofBlurMaskTex.get()); device->setViewport (0, ATOM_Rect2Di(0, 0,_dofBlurMaskTex->getWidth(), _dofBlurMaskTex->getHeight())); drawTexturedFullscreenQuad (device, _material.get(), _dofBlurMaskTex->getWidth(), _dofBlurMaskTex->getHeight()); #endif if( 0 ) { device->setRenderTarget (0, 0); _dofBlurMaskTex->saveToFile ("/textures/rt_test/dofblurMask.dds"); } }
child->get_child(StateId(NAME_BOTTOM))->read_data(&back); UINT width = right - left; UINT height = bottom - top; UINT depth = back - front; // Change units for compressed formats /// @note Depth is not affected if(is_compressed(format)) { width = width / 4 + (((width % 4) == 0) ? 0 : 1); height = height / 4 + (((height % 4) == 0) ? 0 : 1); } UINT size = depth * width * height * texel_size(format); child->get_child(StateId(NAME_DATA))->set_data_size(size); D3D_DEBUG( cout << "CLOCKBOX9: Resizing SLOCKBOX DATA to " << (int)size << endl; ) // Write pitches INT row_pitch; row_pitch = texel_size(format) * width; child->get_child(StateId(NAME_ROW_PITCH))->write_data(&row_pitch); INT slice_pitch; slice_pitch = row_pitch * height; child->get_child(StateId(NAME_SLICE_PITCH))->write_data(&slice_pitch); // Watch node child->add_controller(this); } } void CLockBox9::on_remove_node_child(StateDataNode* parent, StateDataNode* child) { if(child->get_id().name == NAME_LOCKBOX) { // Unwatch node child->remove_controller(this); }
/* Core code contributed by Kevin Behilo, 2/20/04. * * Possible TODO: add code to soften and blend shadow edges * (see aliasing comments in source). * * Definite TODO: the whole thing can be sped up by precalculating the * surface normals once. In fact that should be placed in a separate Shading * Context, so that it could be re-used for quickly re-shading multiple times. */ void vtHeightFieldGrid3d::ShadowCastDib(vtBitmapBase *pBM, const FPoint3 &light_dir, float fLightFactor, float fAmbient, bool progress_callback(int)) { int w = pBM->GetWidth(); int h = pBM->GetHeight(); int gw, gh; GetDimensions(gw, gh); // Compute area that we will sample for shading, bounded by the texel // centers, which are 1/2 texel in from the grid extents. DPoint2 texel_size(m_EarthExtents.Width() / w, m_EarthExtents.Height() / h); DRECT texel_area = m_EarthExtents; texel_area.Grow(-texel_size.x/2, -texel_size.y/2); DPoint2 texel_base(texel_area.left, texel_area.bottom); bool b8bit = (pBM->GetDepth() == 8); int i, j; // These values are hardcoded here but could be exposed in the GUI float sun = 0.7f; // If we have light that's pointing UP, rather than down at the terrain, // then it's only going to take a really long time to produce a // completely dark terrain. We can catch this case up front. if (light_dir.y > 0) { for (i = 0; i < w; i++) { for (j = 0; j < h; j++) { if (b8bit) pBM->ScalePixel8(i, j, fAmbient); else pBM->ScalePixel24(i, j, fAmbient); } } return; } // Create array to hold flags LightMap lightmap(w, h); // This factor is used when applying shading to non-shadowed areas to // try and keep the "contrast" down to a min. (still get "patches" of // dark/light spots though). // It is initialized to 1.0, because in case there are no shadows at all // (such as at noon) we still need a reasonable value. float darkest_shadow = 1.0; // For the vector used to cast shadows, we need it in grid coordinates, // which are (Column,Row) where Row is north. But the direction passed // in uses OpenGL coordinates where Z is south. So flip Z. FPoint3 grid_light_dir = light_dir; grid_light_dir.z = -grid_light_dir.z; // Scale the light vector such that the X or Z component (whichever is // larger) is 1. This is will serve as our direction vector in grid // coordinates, when drawing a line across the grid to cast the shadow. // // Code adapted from aaron_torpy: // http://www.geocities.com/aaron_torpy/algorithms.htm // float f, HScale; if ( fabs(grid_light_dir.x) > fabs(grid_light_dir.z) ) { HScale = m_fXStep; f = fabs(light_dir.x); } else { HScale = m_fZStep; f = fabs(light_dir.z); } grid_light_dir /= f; int i_init, i_final, i_incr; int j_init, j_final, j_incr; if (grid_light_dir.x > 0) { i_init=0; i_final=w; i_incr=1; } else { i_init=w-1; i_final=-1; i_incr=-1; } if (grid_light_dir.z > 0) { j_init=0; j_final=h; j_incr=1; } else { j_init=h-1; j_final=-1; j_incr=-1; } // First pass: find each point that it is in shadow. DPoint2 pos; float shadowheight, elevation; FPoint3 normal; FPoint3 p3; int x, z; float shade; for (j = j_init; j != j_final; j += j_incr) { if (progress_callback != NULL) { if ((j&7) == 0) progress_callback(abs(j-j_init) * 100 / h); } for (i = i_init; i != i_final; i += i_incr) { pos = GridPos(texel_base, texel_size, i, j); FindAltitudeOnEarth(pos, shadowheight, true); if (shadowheight == INVALID_ELEVATION) { // set a flag so we won't visit this one again lightmap.Set(i, j, 1); continue; } bool Under_Out = false; for (int k = 1; Under_Out == false; k++) { x = (int) (i + grid_light_dir.x*k + 0.5f); z = (int) (j + grid_light_dir.z*k + 0.5f); shadowheight += grid_light_dir.y * HScale; if ((x<0) || (x>w-1) || (z<0) || (z>h-1)) { Under_Out = true; // Out of the grid break; } pos = GridPos(texel_base, texel_size, x, z); FindAltitudeOnEarth(pos, elevation, true); // skip holes in the grid if (elevation == INVALID_ELEVATION) continue; if (elevation > shadowheight) { if (k>1) Under_Out = true; // Under the terrain break; } // Combine color and shading. // Only do shadow if we have not shaded this i,j before. if (lightmap.Get(x,z) < 1) { // 3D elevation query to get slope m_Conversion.ConvertFromEarth(pos, p3.x, p3.z); FindAltitudeAtPoint(p3, p3.y, true, 0, &normal); //***************************************** // Here the Sun(r, g, b) = 0 because we are in the shade // therefore I(r, g, b) = Amb(r, g, b) * (0.5*N[z] + 0.5) // shade = sun*normal.Dot(-light_direction) + fAmbient * (0.5f*normal.y + 0.5f); shade = fAmbient * (0.5f*normal.y + 0.5f); //***************************************** //***************************************** if (darkest_shadow > shade) darkest_shadow = shade; //Rather than doing the shading at this point we may want to //simply save the value into the LightMap array. Then apply //some anti-aliasing or edge softening algorithm to the LightMap. //Once that's done, apply the whole LightMap to the DIB. if (b8bit) pBM->ScalePixel8(x, h-1-z, shade); else pBM->ScalePixel24(x, h-1-z, shade); //set a flag to show that this texel has been shaded. // (or set to value of the shading - see comment above) lightmap.Set(x, z, lightmap.Get(x, z)+1); } } } //for i } //for j // For dot-product lighting, we use the normal 3D vector, only inverted // so that we can compare it to the upward-pointing ground normals. FPoint3 inv_light_dir = -light_dir; // Second pass. Now we are going to loop through the LightMap and apply // the full lighting formula to each texel that has not been shaded yet. for (j = 0; j < h; j++) { if (progress_callback != NULL) { if ((j&7) == 0) progress_callback(j * 100 / h); } for (i = 0; i < w; i++) { if (lightmap.Get(i, j) > 0) continue; pos = GridPos(texel_base, texel_size, i, j); // 2D elevation query to check for holes in the grid FindAltitudeOnEarth(pos, elevation, true); if (elevation == INVALID_ELEVATION) continue; // 3D elevation query to get slope m_Conversion.ConvertFromEarth(pos, p3.x, p3.z); FindAltitudeAtPoint(p3, p3.y, true, 0, &normal); //***************************************** //***************************************** //shade formula based on: //http://www.geocities.com/aaron_torpy/algorithms.htm#calc_intensity // The Amb value was arbitrarily chosen // Need to experiment more to determine the best value // Perhaps calculating Sun(r, g, b) and Amb(r, g, b) for a // given time of day (e.g. warmer colors close to sunset) // or give control to user since textures will differ // I(r, g, b) = Sun(r, g, b) * scalarprod(N, v) + Amb(r, g, b) * (0.5*N[z] + 0.5) shade = sun * normal.Dot(inv_light_dir); // It's a reasonable assuption that an angle of 45 degrees is // sufficient to fully illuminate the ground. shade /= .7071f; // Now add ambient component shade += fAmbient * (0.5f*normal.y + 0.5f); // Maybe clipping values can be exposed to the user as well. // Clip - don't shade down below lowest ambient level if (shade < darkest_shadow) shade = darkest_shadow; else if (shade > 1.2f) shade = 1.2f; // Push the value of 'shade' toward 1.0 by the fLightFactor factor. // This means that fLightFactor=0 means no lighting, 1 means full lighting. float diff = 1 - shade; diff = diff * (1 - fLightFactor); shade += diff; // Rather than doing the shading at this point we may want to // simply save the value into the LightMap array. Then apply // some anti-aliasing or edge softening algorithm to the LightMap. // Once that's done, apply the whole LightMap to the DIB. // LightMap[I][J]= shade; // set to value of the shading - see comment above) if (b8bit) pBM->ScalePixel8(i, h-1-j, shade); else pBM->ScalePixel24(i, h-1-j, shade); } } // Possible TODO: Apply edge softening algorithm (?) }
bool ATOM_DOFEffect::render (ATOM_RenderDevice *device) { // 创建RT 和 材质 if( !init(device) ) return false; // 开启SRGB写RT device->enableSRGBWrite(true); //////////////////////////////////////////////////////////////////////////////////////////////// genDofBlurMask(device); sceneToSceneScaled (device); if( _bokeh ) { genBlurBokeh(device); _material->setActiveEffect ("Bokeh"); //ATOM_Vector4f params( _focusDistance, _blurCoefficient, _pixelPerMeter, 0.0f ); //_material->getParameterTable()->setVector("params", params); ATOM_Vector4f texel_size(1.0f/_blurTexs[0]->getWidth(),1.0f/_blurTexs[0]->getHeight(),0,0); _material->getParameterTable()->setVector("texelSize",texel_size); float focus_range_far = _focusRange * 0.5f; float focus_range_near = -_focusRange * 0.5f; ATOM_Vector4f vDofParamsFocus0; vDofParamsFocus0.x = 1.0f / (focus_range_far + 1e-6f); vDofParamsFocus0.y = -_focusDistance / (focus_range_far + 1e-6f); vDofParamsFocus0.z = 1.0f / (focus_range_near + 1e-6f); vDofParamsFocus0.w = -_focusDistance / (focus_range_near + 1e-6f); _material->getParameterTable()->setVector("vDofParamsFocus0", vDofParamsFocus0); ATOM_Vector4f vDofParamsFocus1; vDofParamsFocus1.x = _dofMinz; vDofParamsFocus1.y = _dofMinzScale; vDofParamsFocus1.z = _dofMinZBlendMult; vDofParamsFocus1.w = _blurCoefficient; _material->getParameterTable()->setVector("vDofParamsFocus1", vDofParamsFocus1); _material->getParameterTable()->setFloat("focusPower", _focusPower); /*ATOM_Vector4f vDofParamsFocus2; vDofParamsFocus2.x = _focusDistance; vDofParamsFocus2.y = _focusDistance; vDofParamsFocus2.z = _focusZoneNear; vDofParamsFocus2.w = _focusZoneFar; _material->getParameterTable()->setVector("vDofParamsFocus2", vDofParamsFocus2); */ _material->getParameterTable()->setTexture ("inputTexture", _source.get()); _material->getParameterTable()->setTexture ("bluredTexture", _blurTexs[0].get()); device->setRenderTarget (0, getRenderTarget()); device->setViewport (0, ATOM_Rect2Di(0, 0, getRenderTarget()->getWidth(), getRenderTarget()->getHeight())); drawTexturedFullscreenQuad (device, _material.get(), _source->getWidth(), _source->getHeight()); } else { genBlur(device); _material->setActiveEffect ("default"); ATOM_Vector4f params( _focusDistance, _blurCoefficient, _pixelPerMeter, 0.0f ); _material->getParameterTable()->setVector("params", params); _material->getParameterTable()->setTexture ("inputTexture", _source.get()); _material->getParameterTable()->setTexture ("bluredTexture", _blurTexs[1].get()); device->setRenderTarget (0, getRenderTarget()); device->setViewport (0, ATOM_Rect2Di(0, 0, getRenderTarget()->getWidth(), getRenderTarget()->getHeight())); drawTexturedFullscreenQuad (device, _material.get(), _source->getWidth(), _source->getHeight()); } // 关闭SRGB写 device->enableSRGBWrite(false); return true; }