void NearestSampler(PixelBox& dest, const PixelBox& src) { size_t bytesPerPix = BytesPerPixel(src.format); NEX_ASSERT(bytesPerPix == BytesPerPixel(dest.format)); float dstep = ((float) src.GetDepth() / (float) dest.GetDepth()) * .5f; float hstep = ((float) src.GetHeight() / (float) dest.GetHeight()) * .5f; float wstep = ((float) src.GetWidth() / (float) dest.GetWidth()) * .5f; for (uint32 d = dest.front; d < dest.back; ++d) { size_t doff = (uint32) (dstep * (src.slicePixelPitch * d * 2 + 1)); NEX_ASSERT(doff >= 0 && doff <= src.slicePixelPitch * d); void* destPlane = reinterpret_cast<uint8*>(dest.data) + d * dest.slicePixelPitch * bytesPerPix; for (uint32 h = dest.top; h < dest.bottom; ++h) { size_t hoff = (uint32) ((2 * h * src.rowPixelPitch + 1) * hstep); NEX_ASSERT(hoff >= 0 && hoff <= src.rowPixelPitch * h); uint8* destRow = reinterpret_cast<uint8*>(destPlane) + h * dest.rowPixelPitch * bytesPerPix; for (uint32 w = dest.left; w < dest.right; ++w) { size_t woff = (size_t) ((2 * w + 1) * wstep); NEX_ASSERT(woff >= 0 && woff <= w); uint8* srcData = reinterpret_cast<uint8*>(src.data) + (doff + hoff + woff) * bytesPerPix; // src offset uint8* destData = (destRow + w * bytesPerPix); for (uint32 j = 0; j < bytesPerPix; ++j) destData[j] = srcData[j]; } } } }
void TextureViewGL::Update(nextar::RenderContext* rc, uint32 msg, ContextObject::ContextParamPtr params) { RenderContext_Base_GL* gl = static_cast<RenderContext_Base_GL*>(rc); if (msg & TextureBase::MSG_TEX_READ) { ReadPixels(gl, *const_cast<TextureBase::ReadPixelUpdateParams*>( reinterpret_cast<const TextureBase::ReadPixelUpdateParams*>(params))); return; } // todo Incorrect implementation if (msg & (TextureBase::MSG_TEX_CREATE|TextureBase::MSG_TEX_UPLOAD)) { const TextureBase::UpdateParams& textureParams = *reinterpret_cast<const TextureBase::UpdateParams*>(params); PixelFormat imageFormat = textureParams.textureFormat; if (textureParams.image) imageFormat = textureParams.image->GetFormat(); if (!IsCreated()) { pixelFormat = RenderContext_Base_GL::GetGlPixelFormat(imageFormat, textureParams.textureFormat); if (pixelFormat.internalFormat == GL_NONE) { Warn( "Currently image should be of compatible format with texture!"); return; } texture = gl->CreateTexture(); target = RenderContext_Base_GL::GetGlTextureType( textureParams.type); gl->ActivateTexture(target, texture); if (textureParams.textureFlags & TextureBase::PRE_ALLOCATE_STORAGE) { gl->AllocateTexture(target, (GLint) textureParams.desc.maxMipMapCount, pixelFormat.internalFormat, textureParams.desc.maxWidth, textureParams.desc.maxHeight, textureParams.desc.maxDepth); } } else gl->ActivateTexture(target, texture); if (textureParams.image && (msg & TextureBase::MSG_TEX_UPLOAD)) { Image& img = *textureParams.image; uint32 numMips = img.GetNumMipMaps(); uint32 numFaces = img.GetNumFaces(); NEX_ASSERT(numFaces == 1 || numFaces == 6); GLenum realTarget = target; if (target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) realTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; for (uint32 f = 0; f < numFaces; ++f) { for (uint32 i = 0; i < numMips; ++i) { PixelBox box = img.GetPixelBox(f, i); if (!box.IsSimpleArray()) { Warn("Pixel box has pixel padding. Cannot copy."); continue; } if (textureParams.textureFlags & TextureBase::PRE_ALLOCATE_STORAGE) gl->WriteTextureLevel(realTarget + f, (GLint) (textureParams.baseMipLevel + i), pixelFormat, box.GetWidth(), box.GetHeight(), box.GetDepth(), box.data, box.GetDataSize()); else gl->AllocateTextureLevel(realTarget + f, (GLint) (textureParams.baseMipLevel + i), pixelFormat, box.GetWidth(), box.GetHeight(), box.GetDepth(), box.data, box.GetDataSize()); } gl->SetMipLevels(realTarget + f, textureParams.baseMipLevel, textureParams.lowestMipLevel); } // update number of mip levels } } else if (msg & TextureBase::MSG_TEX_RESIZE) { if (IsCreated()) gl->DestroyTexture(texture); const TextureBase::ResizeParams& textureParams = *reinterpret_cast<const TextureBase::ResizeParams*>(params); texture = gl->CreateTexture(); gl->ActivateTexture(target, texture); gl->AllocateTexture(target, (GLint) textureParams.desc.maxMipMapCount, pixelFormat.internalFormat, textureParams.desc.maxWidth, textureParams.desc.maxHeight, textureParams.desc.maxDepth); } }
void LinearSampler(PixelBox& dest, const PixelBox& src) { NEX_ASSERT(src.format == dest.format); size_t bytesPerPix = BytesPerPixel(src.format); size_t numChannels = formatDescTable[static_cast<uint32>(src.format)].numChannels; NEX_ASSERT(bytesPerPix == BytesPerPixel(dest.format)); float dstep = ((float) src.GetDepth() / (float) dest.GetDepth()) * .5f; float hstep = ((float) src.GetHeight() / (float) dest.GetHeight()) * .5f; float wstep = ((float) src.GetWidth() / (float) dest.GetWidth()) * .5f; for (uint32 d = dest.front; d < dest.back; ++d) { float fdoff1 = (float) (dstep * (d * 2 + 1)); size_t doff1 = (size_t) Math::Floor(fdoff1); size_t doff2 = std::min(doff1 + 1, (size_t) (src.back - 1)); float dweight = fdoff1 - (float) doff1; float dweightOpp = 1 - dweight; NEX_ASSERT(doff1 >= src.front && doff1 < src.back); void* destPlane = reinterpret_cast<uint8*>(dest.data) + d * dest.slicePixelPitch * bytesPerPix; for (uint32 h = dest.top; h < dest.bottom; ++h) { float fhoff1 = (float) ((2 * h + 1) * hstep); size_t hoff1 = (size_t) Math::Floor(fdoff1); size_t hoff2 = std::min(hoff1 + 1, (size_t) (src.bottom - 1)); float hweight = fhoff1 - (float) hoff1; float hweightOpp = 1 - hweight; NEX_ASSERT(hoff1 >= src.top && hoff1 < src.bottom); uint8* destRow = reinterpret_cast<uint8*>(destPlane) + h * dest.rowPixelPitch * bytesPerPix; for (uint32 w = dest.left; w < dest.right; ++w) { float fwoff1 = (2 * w + 1) * wstep; size_t woff1 = (size_t) Math::Floor(fwoff1); size_t woff2 = std::min(woff1 + 1, (size_t) (src.right - 1)); float wweight = fwoff1 - (float) woff1; float wweightOpp = 1 - wweight; NEX_ASSERT(woff1 >= src.left && woff1 < src.right); // ColorChannel d1h1w1, d1h1w2, d2h1w1, d2h1w2, d2h2w2, d2h2w1, d1h2w2, d1h2w1, accum; // extract #define PIXVAL_EXTRACT(to, x,y,z) \ _PackPixel( to, reinterpret_cast<uint8*>(src.data) + \ (x*src.slicePixelPitch + y*src.rowPixelPitch + z)*bytesPerPix, src.format); PIXVAL_EXTRACT(d1h1w1, doff1, hoff1, woff1); PIXVAL_EXTRACT(d1h1w2, doff1, hoff1, woff2); PIXVAL_EXTRACT(d2h1w1, doff2, hoff1, woff1); PIXVAL_EXTRACT(d2h1w2, doff2, hoff1, woff2); PIXVAL_EXTRACT(d2h2w2, doff2, hoff2, woff2); PIXVAL_EXTRACT(d2h2w1, doff2, hoff2, woff1); PIXVAL_EXTRACT(d1h2w2, doff1, hoff2, woff2); PIXVAL_EXTRACT(d1h2w1, doff1, hoff2, woff1); // src offset for (uint32 i = 0; i < numChannels; ++i) { accum.value[i] = d1h1w1.value[i] * (dweightOpp * hweightOpp * wweightOpp) + d1h1w2.value[i] * (dweightOpp * hweightOpp * wweight) + d2h1w1.value[i] * (dweight * hweightOpp * wweightOpp) + d2h1w2.value[i] * (dweight * hweightOpp * wweight) + d2h2w2.value[i] * (dweight * hweight * wweight) + d2h2w1.value[i] * (dweight * hweight * wweightOpp) + d1h2w2.value[i] * (dweight * hweightOpp * wweightOpp) + d1h2w1.value[i] * (dweight * hweightOpp * wweight); } uint8* destData = destRow + w * bytesPerPix; _UnpackPixel(accum, destData, dest.format); } } } }