vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) { vec4 orig = Texel(texture,texture_coords); vec2 coordinatecompressedlocation = vec2(textureoffset % 512, (textureoffset - (textureoffset % 512)) / 512) / 512.0; // Transision from 1d space to 2d space vec4 coordinatecompresed = Texel(posbuffer,coordinatecompressedlocation); // Get the screen location data vec2 coordinate = vec2(coordinatecompresed.r * 255.0 + (coordinatecompresed.g * 255.0 * 255.0), coordinatecompresed.b * 255.0 + (coordinatecompresed.a * 255.0 * 255.0)); // Change 4 bytes to 2 shorts vec4 point = Texel(shadowbuffer,coordinate/textureSize2D(shadowbuffer,0)); // Sample the shadowmap if (point.r < 0.1) { point.r = 0.0;point.g = 0.0;point.b = 0.0; } else { point.r = 1.0;point.g = 1.0;point.b = 1.0; } if (orig.a > 0.0) { orig.a = 1.0; } orig.a *= point.r; return orig*color; }
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) { vec4 orig = Texel(texture,texture_coords); vec4 point = Texel(shadowbuffer,pos/textureSize2D(shadowbuffer,0)); if (type46 && orig.a > 0.0 && orig.a < 1.0) { float id = orig.a * 255.0; if(id < 12.0) { // Unknown use } else if(id > 12.0 && id < 28.0) { orig.rgb = Color1.rgb * (orig.r / 32.0); } else if(id > 28.0 && id < 44.0) { orig.rgb = Color2.rgb * (orig.r / 32.0); } else if(id > 44.0 && id < 66.0f) { orig.rgb = Color3.rgb * (orig.r / 32.0); } else if(id > 66.0 && id < 76.0) { orig.rgb = Color4.rgb * (orig.r / 32.0); } else if(id > 76.0 && id < 92.0) { orig.rgb = Color5.rgb * (orig.r / 32.0); } else { orig.rgb = Color6.rgb * (orig.r / 32.0); } orig.a = 1.0; } if (wall) { if (point.r < 0.1) { point.r = 0.0;point.g = 0.0;point.b = 0.0; } else { point.r = 1.0;point.g = 1.0;point.b = 1.0; } } if (orig.a > 0.0) { orig.a = 1.0; } orig.a *= point.r; return orig*color; }
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) { vec2 pSize = vec2(1.0 / screen.x, 1.0 / screen.y); vec4 col = Texel(texture, texture_coords); for(int i = 1; i <= steps; i++) { col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y - pSize.y * i)); col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y + pSize.y * i)); } col = col / (steps * 2.0 + 1.0); return vec4(col.r, col.g, col.b, 1.0); }
void CNormalGenerator::GeneratePass(int x, int y) { // Generate the low/mid pass values from a fast gaussian filter. static const float flWeightTable[11][11] = { { 0.004f, 0.004f, 0.005f, 0.005f, 0.005f, 0.005f, 0.005f, 0.005f, 0.005f, 0.004f, 0.004f }, { 0.004f, 0.005f, 0.005f, 0.006f, 0.007f, 0.007f, 0.007f, 0.006f, 0.005f, 0.005f, 0.004f }, { 0.005f, 0.005f, 0.006f, 0.008f, 0.009f, 0.009f, 0.009f, 0.008f, 0.006f, 0.005f, 0.005f }, { 0.005f, 0.006f, 0.008f, 0.010f, 0.012f, 0.014f, 0.012f, 0.010f, 0.008f, 0.006f, 0.005f }, { 0.005f, 0.007f, 0.009f, 0.012f, 0.019f, 0.027f, 0.019f, 0.012f, 0.009f, 0.007f, 0.005f }, { 0.005f, 0.007f, 0.009f, 0.014f, 0.027f, 0.054f, 0.027f, 0.014f, 0.009f, 0.007f, 0.005f }, { 0.005f, 0.007f, 0.009f, 0.012f, 0.019f, 0.027f, 0.019f, 0.012f, 0.009f, 0.007f, 0.005f }, { 0.005f, 0.006f, 0.008f, 0.010f, 0.012f, 0.014f, 0.012f, 0.010f, 0.008f, 0.006f, 0.005f }, { 0.005f, 0.005f, 0.006f, 0.008f, 0.009f, 0.009f, 0.009f, 0.008f, 0.006f, 0.005f, 0.005f }, { 0.004f, 0.005f, 0.005f, 0.006f, 0.007f, 0.007f, 0.007f, 0.006f, 0.005f, 0.005f, 0.004f }, { 0.004f, 0.004f, 0.005f, 0.005f, 0.005f, 0.005f, 0.005f, 0.005f, 0.005f, 0.004f, 0.004f }, }; float flLowHeight = 0; float flTotalLowHeight = 0; float flMidHeight = 0; float flTotalMidHeight = 0; for (int i = -10; i <= 10; i++) { for (int j = -10; j <= 10; j++) { size_t iTexel2; if (Texel(x+i, y+j, iTexel2, m_iNormal2Width, m_iNormal2Height)) { size_t iTexelOffset = iTexel2; float flWeight = flWeightTable[(i/2)+5][(j/2)+5]; flLowHeight += m_avecTextureTexels[iTexelOffset].Average() * flWeight; flTotalLowHeight += flWeight; if (i >= -5 && i <= 5 && j >= -5 && j <= 5) { flWeight = flWeightTable[i+5][j+5]; flMidHeight += m_avecTextureTexels[iTexelOffset].Average() * flWeight; flTotalMidHeight += flWeight; } } } } size_t iTexel; Texel(x, y, iTexel, m_iNormal2Width, m_iNormal2Height); m_aflLowPassTexels[iTexel] = flLowHeight/flTotalLowHeight; m_aflMidPassTexels[iTexel] = flMidHeight/flTotalMidHeight; }
static void call(textureType & Texture, typename convert<textureType, T, P>::writeFunc Write, tvec4<T, P> const & Color) { assert(Write); texture const ConvertTexel(Texture.target(), Texture.format(), texture::texelcoord_type(1), 1, 1, 1); textureType Texel(ConvertTexel); Write(Texel, typename textureType::texelcoord_type(0), 0, 0, 0, Color); size_t const BlockSize(block_size(Texture.format())); for(size_t BlockIndex = 0, BlockCount = Texture.size() / BlockSize; BlockIndex < BlockCount; ++BlockIndex) memcpy(static_cast<std::uint8_t*>(Texture.data()) + BlockSize * BlockIndex, Texel.data(), BlockSize); }
static texel_type call(texture_type const & Texture, fetch_type Fetch, samplecoord_type const & SampleCoordWrap, size_type Layer, size_type Face, interpolate_type Level, texel_type const & BorderColor) { size_type const LevelIndex = static_cast<size_type>(Level); texelcoord_type const TexelDim(Texture.dimensions(LevelIndex)); samplecoord_type const TexelLast(samplecoord_type(TexelDim) - samplecoord_type(1)); texelcoord_type const TexelCoord = texelcoord_type(round(SampleCoordWrap * TexelLast)); typename texelcoord_type::bool_type const UseTexelCoord = in_interval(TexelCoord, texelcoord_type(0), TexelDim - 1); texel_type Texel(BorderColor); if(all(UseTexelCoord)) Texel = Fetch(Texture, TexelCoord, Layer, Face, LevelIndex); return Texel; }
vec4 effect(vec4 vcolor, Image texture, vec2 texcoord, vec2 pixel_coords) { vec4 input0 = Texel(texture, texcoord); //exposure knee input0 *= (exp2(input0)*vec4(exposure)); vec4 lumacomponents = vec4(lumcoeff * lumacomponents, 0.0 ); float luminance = dot(input0,lumacomponents); vec4 luma = vec4(luminance); return vec4(luma.rgb * brightness, 1.0); }
vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ) { vec4 c = Texel(texture,texture_coords); if (c.a > 0.0001 && c.a < 0.9999) { float id = c.a * 255.0; if(id < 12.0) { // Unknown use } else if(id > 12.0 && id < 28.0) { c.rgb = Color1.rgb * (c.r / 32.0); } else if(id > 28.0 && id < 44.0) { c.rgb = Color2.rgb * (c.r / 32.0); } else if(id > 44.0 && id < 66.0f) { c.rgb = Color3.rgb * (c.r / 32.0); } else if(id > 66.0 && id < 76.0) { c.rgb = Color4.rgb * (c.r / 32.0); } else if(id > 76.0 && id < 92.0) { c.rgb = Color5.rgb * (c.r / 32.0); } else { c.rgb = Color6.rgb * (c.r / 32.0); } c.a = 1.0; } return c; }
void CAOGenerator::Bleed() { bool* abPixelMask = (bool*)malloc(m_iWidth*m_iHeight*sizeof(bool)); m_pWorkListener->SetAction("Bleeding edges", m_iBleed); for (size_t i = 0; i < m_iBleed; i++) { // This is for pixels that have been set this frame. memset(&abPixelMask[0], 0, m_iWidth*m_iHeight*sizeof(bool)); for (size_t w = 0; w < m_iWidth; w++) { for (size_t h = 0; h < m_iHeight; h++) { Vector vecTotal(0,0,0); size_t iTotal = 0; size_t iTexel; // If the texel has the mask on then it already has a value so skip it. if (Texel(w, h, iTexel, true)) continue; if (Texel(w-1, h-1, iTexel)) { vecTotal += m_avecShadowValues[iTexel]; iTotal++; } if (Texel(w-1, h, iTexel)) { vecTotal += m_avecShadowValues[iTexel]; iTotal++; } if (Texel(w-1, h+1, iTexel)) { vecTotal += m_avecShadowValues[iTexel]; iTotal++; } if (Texel(w, h+1, iTexel)) { vecTotal += m_avecShadowValues[iTexel]; iTotal++; } if (Texel(w+1, h+1, iTexel)) { vecTotal += m_avecShadowValues[iTexel]; iTotal++; } if (Texel(w+1, h, iTexel)) { vecTotal += m_avecShadowValues[iTexel]; iTotal++; } if (Texel(w+1, h-1, iTexel)) { vecTotal += m_avecShadowValues[iTexel]; iTotal++; } if (Texel(w, h-1, iTexel)) { vecTotal += m_avecShadowValues[iTexel]; iTotal++; } Texel(w, h, iTexel, false); if (iTotal) { vecTotal /= (float)iTotal; m_avecShadowValues[iTexel] = vecTotal; abPixelMask[iTexel] = true; } } } for (size_t p = 0; p < m_iWidth*m_iHeight; p++) m_bPixelMask[p] |= abPixelMask[p]; m_pWorkListener->WorkProgress(i); if (m_bStopGenerating) break; } free(abPixelMask); }
vec4 checkTexelBounds(Image texture, vec2 coords, vec2 bounds) { vec2 ss = step(coords, vec2(bounds.x, 1.0)) * step(vec2(0.0, bounds.y), coords); return Texel(texture, coords) * ss.x * ss.y; }
bool CTexelGenerator::Texel(size_t w, size_t h, size_t& iTexel, bool bUseMask) { return Texel(w, h, iTexel, m_iWidth, m_iHeight, bUseMask?m_abTexelMask:NULL); }
void CTexelGenerator::FindHiResMeshLocation(CConversionMeshInstance* pMeshInstance, CConversionFace* pFace, CConversionVertex* pV1, CConversionVertex* pV2, CConversionVertex* pV3, size_t i, size_t j, raytrace::CRaytracer* pTracer) { CConversionMesh* pMesh = pMeshInstance->GetMesh(); Vector vu1 = pMesh->GetUV(pV1->vu); Vector vu2 = pMesh->GetUV(pV2->vu); Vector vu3 = pMesh->GetUV(pV3->vu); float flU = ((float)i + 0.5f)/(float)m_iWidth; float flV = ((float)j + 0.5f)/(float)m_iHeight; bool bInside = PointInTriangle(Vector(flU,flV,0), vu1, vu2, vu3); if (!bInside) return; Vector v1 = pMeshInstance->GetVertex(pV1->v); Vector v2 = pMeshInstance->GetVertex(pV2->v); Vector v3 = pMeshInstance->GetVertex(pV3->v); // Find where the UV is in world space. // First build 2x2 a "matrix" of the UV values. float mta = vu2.x - vu1.x; float mtb = vu3.x - vu1.x; float mtc = vu2.y - vu1.y; float mtd = vu3.y - vu1.y; // Invert it. float d = mta*mtd - mtb*mtc; float mtia = mtd / d; float mtib = -mtb / d; float mtic = -mtc / d; float mtid = mta / d; // Now build a 2x3 "matrix" of the vertices. float mva = v2.x - v1.x; float mvb = v3.x - v1.x; float mvc = v2.y - v1.y; float mvd = v3.y - v1.y; float mve = v2.z - v1.z; float mvf = v3.z - v1.z; // Multiply them together. // [a b] [a b] [a b] // [c d] * [c d] = [c d] // [e f] [e f] // Really wish I had a matrix math library about now! float mra = mva*mtia + mvb*mtic; float mrb = mva*mtib + mvb*mtid; float mrc = mvc*mtia + mvd*mtic; float mrd = mvc*mtib + mvd*mtid; float mre = mve*mtia + mvf*mtic; float mrf = mve*mtib + mvf*mtid; // These vectors should be the U and V axis in world space. Vector vecUAxis(mra, mrc, mre); Vector vecVAxis(mrb, mrd, mrf); Vector vecUVOrigin = v1 - vecUAxis * vu1.x - vecVAxis * vu1.y; Vector vecUVPosition = vecUVOrigin + vecUAxis * flU + vecVAxis * flV; Vector vecNormal = pFace->GetNormal(vecUVPosition, pMeshInstance); size_t iTexel; Texel(i, j, iTexel, false); // Maybe use a closest-poly check here to eliminate the need for some raytracing? raytrace::CTraceResult trFront; bool bHitFront = pTracer->Raytrace(Ray(vecUVPosition, vecNormal), &trFront); raytrace::CTraceResult trBack; bool bHitBack = pTracer->Raytrace(Ray(vecUVPosition, -vecNormal), &trBack); #ifdef NORMAL_DEBUG GetParallelizer()->LockData(); if (bHitFront && (vecUVPosition - trFront.m_vecHit).LengthSqr() > 0.001f) SMAKWindow()->AddDebugLine(vecUVPosition, trFront.m_vecHit); if (bHitBack && (vecUVPosition - trBack.m_vecHit).LengthSqr() > 0.001f) SMAKWindow()->AddDebugLine(vecUVPosition, trBack.m_vecHit); GetParallelizer()->UnlockData(); #endif if (!bHitBack && !bHitFront) return; raytrace::CTraceResult* trFinal; if (bHitFront && !bHitBack) trFinal = &trFront; else if (bHitBack && !bHitFront) trFinal = &trBack; else { float flHitFront = (vecUVPosition - trFront.m_vecHit).LengthSqr(); float flHitBack = (vecUVPosition - trBack.m_vecHit).LengthSqr(); if (flHitFront < flHitBack) trFinal = &trFront; else trFinal = &trBack; } #ifdef NORMAL_DEBUG GetParallelizer()->LockData(); // SMAKWindow()->AddDebugLine(vecUVPosition, vecUVPosition+vecHitNormal); if (bHitFront && (vecUVPosition - trFront.m_vecHit).LengthSqr() > 0.001f) SMAKWindow()->AddDebugLine(trFront.m_vecHit, trFront.m_vecHit + trFront.m_pFace->GetNormal(trFront.m_vecHit, trFront.m_pMeshInstance)); if (bHitBack && (vecUVPosition - trBack.m_vecHit).LengthSqr() > 0.001f) SMAKWindow()->AddDebugLine(trBack.m_vecHit, trBack.m_vecHit + trBack.m_pFace->GetNormal(trBack.m_vecHit, trBack.m_pMeshInstance)); GetParallelizer()->UnlockData(); #endif for (size_t i = 0; i < m_apMethods.size(); i++) { m_apMethods[i]->GenerateTexel(iTexel, pMeshInstance, pFace, pV1, pV2, pV3, trFinal, vecUVPosition, pTracer); } }
void CAOGenerator::GenerateTriangleByTexel(CConversionMeshInstance* pMeshInstance, CConversionFace* pFace, size_t v1, size_t v2, size_t v3, raytrace::CRaytracer* pTracer, size_t& iRendered) { CConversionVertex* pV1 = pFace->GetVertex(v1); CConversionVertex* pV2 = pFace->GetVertex(v2); CConversionVertex* pV3 = pFace->GetVertex(v3); CConversionMesh* pMesh = pMeshInstance->GetMesh(); Vector vu1 = pMesh->GetUV(pV1->vu); Vector vu2 = pMesh->GetUV(pV2->vu); Vector vu3 = pMesh->GetUV(pV3->vu); Vector vecLoUV = vu1; Vector vecHiUV = vu1; if (vu2.x < vecLoUV.x) vecLoUV.x = vu2.x; if (vu3.x < vecLoUV.x) vecLoUV.x = vu3.x; if (vu2.x > vecHiUV.x) vecHiUV.x = vu2.x; if (vu3.x > vecHiUV.x) vecHiUV.x = vu3.x; if (vu2.y < vecLoUV.y) vecLoUV.y = vu2.y; if (vu3.y < vecLoUV.y) vecLoUV.y = vu3.y; if (vu2.y > vecHiUV.y) vecHiUV.y = vu2.y; if (vu3.y > vecHiUV.y) vecHiUV.y = vu3.y; size_t iLoX = (size_t)(vecLoUV.x * m_iWidth); size_t iLoY = (size_t)(vecLoUV.y * m_iHeight); size_t iHiX = (size_t)(vecHiUV.x * m_iWidth); size_t iHiY = (size_t)(vecHiUV.y * m_iHeight); for (size_t i = iLoX; i <= iHiX; i++) { for (size_t j = iLoY; j <= iHiY; j++) { float flU = ((float)i + 0.5f)/(float)m_iWidth; float flV = ((float)j + 0.5f)/(float)m_iHeight; bool bInside = PointInTriangle(Vector(flU,flV,0), vu1, vu2, vu3); if (!bInside) continue; Vector v1 = pMeshInstance->GetVertex(pV1->v); Vector v2 = pMeshInstance->GetVertex(pV2->v); Vector v3 = pMeshInstance->GetVertex(pV3->v); Vector vn1 = pMeshInstance->GetNormal(pV1->vn); Vector vn2 = pMeshInstance->GetNormal(pV2->vn); Vector vn3 = pMeshInstance->GetNormal(pV3->vn); // Find where the UV is in world space. // First build 2x2 a "matrix" of the UV values. float mta = vu2.x - vu1.x; float mtb = vu3.x - vu1.x; float mtc = vu2.y - vu1.y; float mtd = vu3.y - vu1.y; // Invert it. float d = mta*mtd - mtb*mtc; float mtia = mtd / d; float mtib = -mtb / d; float mtic = -mtc / d; float mtid = mta / d; // Now build a 2x3 "matrix" of the vertices. float mva = v2.x - v1.x; float mvb = v3.x - v1.x; float mvc = v2.y - v1.y; float mvd = v3.y - v1.y; float mve = v2.z - v1.z; float mvf = v3.z - v1.z; // Multiply them together. // [a b] [a b] [a b] // [c d] * [c d] = [c d] // [e f] [e f] // Really wish I had a matrix math library about now! float mra = mva*mtia + mvb*mtic; float mrb = mva*mtib + mvb*mtid; float mrc = mvc*mtia + mvd*mtic; float mrd = mvc*mtib + mvd*mtid; float mre = mve*mtia + mvf*mtic; float mrf = mve*mtib + mvf*mtid; // These vectors should be the U and V axis in world space. Vector vecUAxis(mra, mrc, mre); Vector vecVAxis(mrb, mrd, mrf); Vector vecUVOrigin = v1 - vecUAxis * vu1.x - vecVAxis * vu1.y; Vector vecUVPosition = vecUVOrigin + vecUAxis * flU + vecVAxis * flV; Vector vecNormal; if (m_bCreaseEdges) vecNormal = pFace->GetNormal(); else { float wv1 = DistanceToLine(vecUVPosition, v2, v3) / DistanceToLine(v1, v2, v3); float wv2 = DistanceToLine(vecUVPosition, v1, v3) / DistanceToLine(v2, v1, v3); float wv3 = DistanceToLine(vecUVPosition, v1, v2) / DistanceToLine(v3, v1, v2); vecNormal = vn1 * wv1 + vn2 * wv2 + vn3 * wv3; } if (ao_debug.GetInt() > 1) SMAKWindow()->AddDebugLine(vecUVPosition, vecUVPosition + vecNormal/2); size_t iTexel; if (!Texel(i, j, iTexel, false)) continue; if (m_eAOMethod == AOMETHOD_RENDER) { // Render the scene from this location m_avecShadowValues[iTexel] += RenderSceneFromPosition(vecUVPosition, vecNormal, pFace); } else if (m_eAOMethod == AOMETHOD_RAYTRACE) { RaytraceSceneMultithreaded(pTracer, vecUVPosition, vecNormal, pMeshInstance, pFace, iTexel); } m_aiShadowReads[iTexel]++; m_bPixelMask[iTexel] = true; m_pWorkListener->WorkProgress(++iRendered); if (m_bStopGenerating) break; } if (m_bStopGenerating) break; } }
TextureComp::TextureComp(GLuint textureID) : textureID_(textureID), transform_(Texel(0.f, 0.f), Texel(0.f, 0.f), Texel(1.f, 1.f)) { }
const Texel operator +(const Texel &lhs, const Texel &rhs) { return Texel(lhs.x + rhs.x, lhs.y + rhs.y); }
const Texel operator *(const Texel &lhs, const float rhs) { return Texel(lhs.x * rhs, lhs.y * rhs); }
void CNormalGenerator::NormalizeHeightValue(size_t x, size_t y) { if (!m_avecTextureTexels.size()) return; float flHiScale = ((m_iNormal2Width+m_iNormal2Height)/2.0f)/200.0f * m_flNormalTextureDepth; float flMidScale = ((m_iNormal2Width+m_iNormal2Height)/2.0f)/100.0f * m_flNormalTextureDepth; float flLowScale = ((m_iNormal2Width+m_iNormal2Height)/2.0f)/50.0f * m_flNormalTextureDepth; size_t iTexel; Texel(x, y, iTexel, m_iNormal2Width, m_iNormal2Height, false); tvector<Vector> avecHeights; float flHeight = m_avecTextureTexels[iTexel].Average() * flHiScale; float flMidPass = m_aflMidPassTexels[iTexel] * flMidScale; float flLowPass = m_aflLowPassTexels[iTexel] * flLowScale; Vector vecCenter((float)x, (float)y, flHeight*m_flNormalTextureHiDepth + flMidPass*m_flNormalTextureMidDepth + flLowPass*m_flNormalTextureLoDepth); Vector vecNormal(0,0,0); if (Texel(x+1, y, iTexel, m_iNormal2Width, m_iNormal2Height, false)) { flHeight = m_avecTextureTexels[iTexel].Average() * flHiScale; flMidPass = m_aflMidPassTexels[iTexel] * flMidScale; flLowPass = m_aflLowPassTexels[iTexel] * flLowScale; Vector vecNeighbor(x+1.0f, (float)y, flHeight*m_flNormalTextureHiDepth + flMidPass*m_flNormalTextureMidDepth + flLowPass*m_flNormalTextureLoDepth); vecNormal += (vecNeighbor-vecCenter).Normalized().Cross(Vector(0, 1, 0)); } if (Texel(x-1, y, iTexel, m_iNormal2Width, m_iNormal2Height, false)) { flHeight = m_avecTextureTexels[iTexel].Average() * flHiScale; flMidPass = m_aflMidPassTexels[iTexel] * flMidScale; flLowPass = m_aflLowPassTexels[iTexel] * flLowScale; Vector vecNeighbor(x-1.0f, (float)y, flHeight*m_flNormalTextureHiDepth + flMidPass*m_flNormalTextureMidDepth + flLowPass*m_flNormalTextureLoDepth); vecNormal += (vecNeighbor-vecCenter).Normalized().Cross(Vector(0, -1, 0)); } if (Texel(x, y+1, iTexel, m_iNormal2Width, m_iNormal2Height, false)) { flHeight = m_avecTextureTexels[iTexel].Average() * flHiScale; flMidPass = m_aflMidPassTexels[iTexel] * flMidScale; flLowPass = m_aflLowPassTexels[iTexel] * flLowScale; Vector vecNeighbor((float)x, y+1.0f, flHeight*m_flNormalTextureHiDepth + flMidPass*m_flNormalTextureMidDepth + flLowPass*m_flNormalTextureLoDepth); vecNormal += (vecNeighbor-vecCenter).Normalized().Cross(Vector(-1, 0, 0)); } if (Texel(x, y-1, iTexel, m_iNormal2Width, m_iNormal2Height, false)) { flHeight = m_avecTextureTexels[iTexel].Average() * flHiScale; flMidPass = m_aflMidPassTexels[iTexel] * flMidScale; flLowPass = m_aflLowPassTexels[iTexel] * flLowScale; Vector vecNeighbor((float)x, y-1.0f, flHeight*m_flNormalTextureHiDepth + flMidPass*m_flNormalTextureMidDepth + flLowPass*m_flNormalTextureLoDepth); vecNormal += (vecNeighbor-vecCenter).Normalized().Cross(Vector(1, 0, 0)); } vecNormal.Normalize(); for (size_t i = 0; i < 3; i++) vecNormal[i] = RemapVal(vecNormal[i], -1.0f, 1.0f, 0.0f, 0.99f); // Don't use 1.0 because of integer overflow. // Don't need to lock the data because we're guaranteed never to access the same texel twice due to the generation method. m_avecNormal2Texels[iTexel] = vecNormal; }