diff --git a/docs/api/python/frozen/pyopencolorio_gpushaderdesc.rst b/docs/api/python/frozen/pyopencolorio_gpushaderdesc.rst index 6fb50e827b..5f8234b523 100644 --- a/docs/api/python/frozen/pyopencolorio_gpushaderdesc.rst +++ b/docs/api/python/frozen/pyopencolorio_gpushaderdesc.rst @@ -195,7 +195,7 @@ :module: PyOpenColorIO - .. py:method:: GpuShaderDesc.add3DTexture(self: PyOpenColorIO.GpuShaderDesc, textureName: str, samplerName: str, edgeLen: int, interpolation: PyOpenColorIO.Interpolation, values: buffer) -> None + .. py:method:: GpuShaderDesc.add3DTexture(self: PyOpenColorIO.GpuShaderDesc, textureName: str, samplerName: str, edgeLen: int, channel: PyOpenColorIO.GpuShaderCreator.TextureType, interpolation: PyOpenColorIO.Interpolation, values: buffer) -> None :module: PyOpenColorIO Add a 3D texture with RGB channel type. @@ -477,6 +477,8 @@ .. py:property:: Texture3D.interpolation :module: PyOpenColorIO.GpuShaderDesc + .. py:property:: Texture3D.channel + :module: PyOpenColorIO.GpuShaderDesc .. py:property:: Texture3D.samplerName :module: PyOpenColorIO.GpuShaderDesc diff --git a/include/OpenColorIO/OpenColorIO.h b/include/OpenColorIO/OpenColorIO.h index a62b76904e..61c85f8a9d 100644 --- a/include/OpenColorIO/OpenColorIO.h +++ b/include/OpenColorIO/OpenColorIO.h @@ -3268,7 +3268,8 @@ class OCIOEXPORT GpuShaderCreator enum TextureType { TEXTURE_RED_CHANNEL, ///< Only need a red channel texture - TEXTURE_RGB_CHANNEL ///< Need a RGB texture + TEXTURE_RGB_CHANNEL, ///< Need a RGB texture + TEXTURE_RGBA_CHANNEL ///< Need a RGBA texture }; /** @@ -3305,6 +3306,7 @@ class OCIOEXPORT GpuShaderCreator virtual void add3DTexture(const char * textureName, const char * samplerName, unsigned edgelen, + TextureType channel, Interpolation interpolation, const float * values) = 0; @@ -3552,6 +3554,7 @@ class OCIOEXPORT GpuShaderDesc : public GpuShaderCreator const char *& textureName, const char *& samplerName, unsigned & edgelen, + TextureType& channel, Interpolation & interpolation) const = 0; virtual void get3DTextureValues(unsigned index, const float *& values) const = 0; diff --git a/src/OpenColorIO/GpuShader.cpp b/src/OpenColorIO/GpuShader.cpp index 7fbc30b43a..8c55f978a1 100644 --- a/src/OpenColorIO/GpuShader.cpp +++ b/src/OpenColorIO/GpuShader.cpp @@ -246,6 +246,7 @@ class PrivateImpl void add3DTexture(const char * textureName, const char * samplerName, unsigned edgelen, + GenericGpuShaderDesc::TextureType channel, Interpolation interpolation, const float * values) { @@ -258,7 +259,7 @@ class PrivateImpl } Texture t(textureName, samplerName, edgelen, edgelen, edgelen, - GpuShaderDesc::TEXTURE_RGB_CHANNEL, 3, + channel, 3, interpolation, values); m_textures3D.push_back(t); } @@ -267,6 +268,7 @@ class PrivateImpl const char *& textureName, const char *& samplerName, unsigned & edgelen, + GenericGpuShaderDesc::TextureType& channel, Interpolation & interpolation) const { if(index >= m_textures3D.size()) @@ -281,6 +283,7 @@ class PrivateImpl textureName = t.m_textureName.c_str(); samplerName = t.m_samplerName.c_str(); edgelen = t.m_width; + channel = t.m_type; interpolation = t.m_interp; } @@ -520,19 +523,21 @@ unsigned GenericGpuShaderDesc::getNum3DTextures() const noexcept void GenericGpuShaderDesc::add3DTexture(const char * textureName, const char * samplerName, unsigned edgelen, + TextureType channel, Interpolation interpolation, const float * values) { - getImplGeneric()->add3DTexture(textureName, samplerName, edgelen, interpolation, values); + getImplGeneric()->add3DTexture(textureName, samplerName, edgelen, channel, interpolation, values); } void GenericGpuShaderDesc::get3DTexture(unsigned index, const char *& textureName, const char *& samplerName, unsigned & edgelen, + TextureType & channel, Interpolation & interpolation) const { - getImplGeneric()->get3DTexture(index, textureName, samplerName, edgelen, interpolation); + getImplGeneric()->get3DTexture(index, textureName, samplerName, edgelen, channel, interpolation); } void GenericGpuShaderDesc::get3DTextureValues(unsigned index, const float *& values) const diff --git a/src/OpenColorIO/GpuShader.h b/src/OpenColorIO/GpuShader.h index e9c39d56b1..29ad603629 100644 --- a/src/OpenColorIO/GpuShader.h +++ b/src/OpenColorIO/GpuShader.h @@ -71,12 +71,14 @@ class GenericGpuShaderDesc : public GpuShaderDesc void add3DTexture(const char * textureName, const char * samplerName, unsigned edgelen, + TextureType channel, Interpolation interpolation, const float * values) override; void get3DTexture(unsigned index, const char *& textureName, const char *& samplerName, unsigned & edgelen, + TextureType& channel, Interpolation & interpolation) const override; void get3DTextureValues(unsigned index, const float *& value) const override; diff --git a/src/OpenColorIO/GpuShaderUtils.cpp b/src/OpenColorIO/GpuShaderUtils.cpp index a3adefbdc0..3d48e22bba 100644 --- a/src/OpenColorIO/GpuShaderUtils.cpp +++ b/src/OpenColorIO/GpuShaderUtils.cpp @@ -222,6 +222,32 @@ std::string getMatrixValues(const T * mtx, GpuLanguage lang, bool transpose) return vals; } + +void RGBtoRGBATexture(const float* lutValues, int valueCount, std::vector& float4AdaptedLutValues) +{ + if(valueCount % 3 != 0) + { + throw Exception("Value count should be divisible by 3."); + } + + valueCount = valueCount * 4 / 3; + if(lutValues != nullptr) + { + float4AdaptedLutValues.resize(valueCount); + const float *rgbLutValuesIt = lutValues; + float *rgbaLutValuesIt = float4AdaptedLutValues.data(); + const float *end = rgbaLutValuesIt + valueCount; + + while(rgbaLutValuesIt != end) + { + *rgbaLutValuesIt++ = *rgbLutValuesIt++; + *rgbaLutValuesIt++ = *rgbLutValuesIt++; + *rgbaLutValuesIt++ = *rgbLutValuesIt++; + *rgbaLutValuesIt++ = 1.0f; + } + } +} + GpuShaderText::GpuShaderLine::GpuShaderLine(GpuShaderText * text) : m_text(text) { diff --git a/src/OpenColorIO/GpuShaderUtils.h b/src/OpenColorIO/GpuShaderUtils.h index b533110749..2238ff227f 100644 --- a/src/OpenColorIO/GpuShaderUtils.h +++ b/src/OpenColorIO/GpuShaderUtils.h @@ -260,6 +260,9 @@ void AddLinToLogShader(GpuShaderCreatorRcPtr & shaderCreator, GpuShaderText & st // Convert "grading log" values to scene-linear. void AddLogToLinShader(GpuShaderCreatorRcPtr & shaderCreator, GpuShaderText & st); +// Texture converter from RGB to RGBA +void RGBtoRGBATexture(const float* lutValues, int valueCount, std::vector& float4AdaptedLutValues); + } // namespace OCIO_NAMESPACE #endif diff --git a/src/OpenColorIO/ops/lut1d/Lut1DOpGPU.cpp b/src/OpenColorIO/ops/lut1d/Lut1DOpGPU.cpp index 26a5c7d712..c0af8eff8c 100644 --- a/src/OpenColorIO/ops/lut1d/Lut1DOpGPU.cpp +++ b/src/OpenColorIO/ops/lut1d/Lut1DOpGPU.cpp @@ -155,27 +155,52 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator, const unsigned long length = lutData->getArray().getLength(); const unsigned long width = std::min(length, defaultMaxWidth); const unsigned long height = (length / defaultMaxWidth) + 1; - const unsigned long numChannels = lutData->getArray().getNumColorComponents(); + unsigned long numChannels = lutData->getArray().getNumColorComponents(); // Note: The 1D LUT needs a GPU texture for the Look-up table implementation. // However, the texture type & content may vary based on the number of channels // i.e. when all channels are identical a F32 Red GPU texture is enough. - + const bool singleChannel = (numChannels == 1); + // When shader language is metal, we want to return a texture in + // RGBA format instead of RGB. + if (shaderCreator ->getLanguage() == GPU_LANGUAGE_MSL_2_0 && numChannels == 3) + { + numChannels = 4; + } + // Adjust LUT texture to allow for correct 2d linear interpolation, if needed. std::vector values; values.reserve(width * height * numChannels); - if (singleChannel) // i.e. numChannels == 1. + GpuShaderCreator::TextureType channel = GpuShaderCreator::TEXTURE_RED_CHANNEL; + switch (numChannels) { + case 1: CreatePaddedRedChannel(width, height, lutData->getArray().getValues(), values); - } - else - { + channel = GpuShaderCreator::TEXTURE_RED_CHANNEL; + break; + case 3: CreatePaddedLutChannels(width, height, lutData->getArray().getValues(), values); + channel = GpuShaderCreator::TEXTURE_RGB_CHANNEL; + break; + case 4: + { + std::vector paddedChannels; + paddedChannels.reserve(width * height * 3); + CreatePaddedLutChannels(width, height, lutData->getArray().getValues(), paddedChannels); + // Insert a place holder alpha channel with value of 1. This is to support RGBA + // texture format for Metal shading language. + RGBtoRGBATexture(paddedChannels.data(), width * height * 3, values); + channel = GpuShaderCreator::TEXTURE_RGBA_CHANNEL; + break; } + default: + throw Exception("Invalid number of texture channels."); + break; + } // Register the RGB LUT. @@ -203,8 +228,7 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator, GpuShaderText::getSamplerName(name).c_str(), width, height, - singleChannel ? GpuShaderCreator::TEXTURE_RED_CHANNEL - : GpuShaderCreator::TEXTURE_RGB_CHANNEL, + channel, dimensions, lutData->getConcreteInterpolation(), &values[0]); diff --git a/src/OpenColorIO/ops/lut3d/Lut3DOpGPU.cpp b/src/OpenColorIO/ops/lut3d/Lut3DOpGPU.cpp index 786f52961c..fb31b07320 100644 --- a/src/OpenColorIO/ops/lut3d/Lut3DOpGPU.cpp +++ b/src/OpenColorIO/ops/lut3d/Lut3DOpGPU.cpp @@ -10,7 +10,6 @@ #include "ops/lut3d/Lut3DOpGPU.h" #include "utils/StringUtils.h" - namespace OCIO_NAMESPACE { @@ -38,12 +37,30 @@ void GetLut3DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator, ConstLut3DO { samplerInterpolation = INTERP_NEAREST; } - // (Using CacheID here to potentially allow reuse of existing textures.) - shaderCreator->add3DTexture(name.c_str(), + + if(shaderCreator->getLanguage() == GPU_LANGUAGE_MSL_2_0){ + unsigned edgelen = lutData->getGridSize(); + std::vector float4AdaptedLutValues; + RGBtoRGBATexture(&lutData->getArray()[0], 3*edgelen*edgelen*edgelen, float4AdaptedLutValues); + + shaderCreator->add3DTexture(name.c_str(), GpuShaderText::getSamplerName(name).c_str(), - lutData->getGridSize(), + edgelen, + GpuShaderCreator::TEXTURE_RGBA_CHANNEL, samplerInterpolation, - &lutData->getArray()[0]); + float4AdaptedLutValues.data()); + } + else + { + // All other languages + // (Using CacheID here to potentially allow reuse of existing textures.) + shaderCreator->add3DTexture(name.c_str(), + GpuShaderText::getSamplerName(name).c_str(), + lutData->getGridSize(), + GpuShaderCreator::TEXTURE_RGB_CHANNEL, + samplerInterpolation, + &lutData->getArray()[0]); + } { GpuShaderText ss(shaderCreator->getLanguage()); diff --git a/src/bindings/python/PyGpuShaderDesc.cpp b/src/bindings/python/PyGpuShaderDesc.cpp index 24bb82412a..ae5e435019 100644 --- a/src/bindings/python/PyGpuShaderDesc.cpp +++ b/src/bindings/python/PyGpuShaderDesc.cpp @@ -38,6 +38,7 @@ struct Texture3D std::string m_textureName; std::string m_samplerName; unsigned m_edgelen; + GpuShaderDesc::TextureType m_channel; Interpolation m_interpolation; GpuShaderDescRcPtr m_shaderDesc; int m_index; @@ -129,6 +130,9 @@ void bindPyGpuShaderDesc(py::module & m) case GpuShaderDesc::TEXTURE_RGB_CHANNEL: numChannels = 3; break; + case GpuShaderDesc::TEXTURE_RGBA_CHANNEL: + numChannels = 4; + break; default: throw Exception("Error: Unsupported texture type"); } @@ -160,6 +164,7 @@ void bindPyGpuShaderDesc(py::module & m) const std::string & textureName, const std::string & samplerName, unsigned edgelen, + GpuShaderDesc::TextureType channel, Interpolation interpolation, const py::buffer & values) { @@ -172,10 +177,11 @@ void bindPyGpuShaderDesc(py::module & m) self->add3DTexture(textureName.c_str(), samplerName.c_str(), edgelen, + channel, interpolation, static_cast(info.ptr)); }, - "textureName"_a, "samplerName"_a, "edgeLen"_a, "interpolation"_a, "values"_a, + "textureName"_a, "samplerName"_a, "edgeLen"_a, "channel"_a, "interpolation"_a, "values"_a, DOC(GpuShaderCreator, add3DTexture)) .def("get3DTextures", [](GpuShaderDescRcPtr & self) { @@ -266,6 +272,9 @@ void bindPyGpuShaderDesc(py::module & m) case GpuShaderDesc::TEXTURE_RGB_CHANNEL: numChannels = 3; break; + case GpuShaderDesc::TEXTURE_RGBA_CHANNEL: + numChannels = 4; + break; default: throw Exception("Error: Unsupported texture type"); } @@ -323,6 +332,7 @@ void bindPyGpuShaderDesc(py::module & m) .def_readonly("textureName", &Texture3D::m_textureName) .def_readonly("samplerName", &Texture3D::m_samplerName) .def_readonly("edgeLen", &Texture3D::m_edgelen) + .def_readonly("channel", &Texture3D::m_channel) .def_readonly("interpolation", &Texture3D::m_interpolation) .def("getValues", [](Texture3D & self) { @@ -350,10 +360,11 @@ void bindPyGpuShaderDesc(py::module & m) const char * textureName = nullptr; const char * samplerName = nullptr; unsigned edgelen; + GpuShaderDesc::TextureType channel; Interpolation interpolation; - it.m_obj->get3DTexture(i, textureName, samplerName, edgelen, interpolation); + it.m_obj->get3DTexture(i, textureName, samplerName, edgelen, channel, interpolation); - return { textureName, samplerName, edgelen, interpolation, it.m_obj, i }; + return { textureName, samplerName, edgelen, channel, interpolation, it.m_obj, i }; }) .def("__iter__", [](Texture3DIterator & it) -> Texture3DIterator & { @@ -366,10 +377,11 @@ void bindPyGpuShaderDesc(py::module & m) const char * textureName = nullptr; const char * samplerName = nullptr; unsigned edgelen; + GpuShaderDesc::TextureType channel; Interpolation interpolation; - it.m_obj->get3DTexture(i, textureName, samplerName, edgelen, interpolation); + it.m_obj->get3DTexture(i, textureName, samplerName, edgelen, channel, interpolation); - return { textureName, samplerName, edgelen, interpolation, it.m_obj, i }; + return { textureName, samplerName, edgelen, channel, interpolation, it.m_obj, i }; }); } diff --git a/src/libutils/oglapphelpers/glsl.cpp b/src/libutils/oglapphelpers/glsl.cpp index 16709fa3e7..711b061512 100644 --- a/src/libutils/oglapphelpers/glsl.cpp +++ b/src/libutils/oglapphelpers/glsl.cpp @@ -319,8 +319,9 @@ void OpenGLBuilder::allocateAllTextures(unsigned startIndex) const char * textureName = nullptr; const char * samplerName = nullptr; unsigned edgelen = 0; + GpuShaderCreator:: TextureType channel = GpuShaderCreator::TEXTURE_RGB_CHANNEL; Interpolation interpolation = INTERP_LINEAR; - m_shaderDesc->get3DTexture(idx, textureName, samplerName, edgelen, interpolation); + m_shaderDesc->get3DTexture(idx, textureName, samplerName, edgelen, channel, interpolation); if(!textureName || !*textureName || !samplerName || !*samplerName diff --git a/src/libutils/oglapphelpers/metalapp.mm b/src/libutils/oglapphelpers/metalapp.mm index be46d4e1b6..40df4b4cbd 100644 --- a/src/libutils/oglapphelpers/metalapp.mm +++ b/src/libutils/oglapphelpers/metalapp.mm @@ -264,9 +264,10 @@ vertex VertexOut ColorCorrectionVS(unsigned int vId [[ vertex_id ]]) const char* textureName; const char* samplerName; unsigned int edgeLen; + GpuShaderDesc::TextureType channel; Interpolation interpolation; - shaderDesc->get3DTexture(i, textureName, samplerName, edgeLen, interpolation); + shaderDesc->get3DTexture(i, textureName, samplerName, edgeLen, channel, interpolation); main << ", texture3d " << textureName diff --git a/src/libutils/oglapphelpers/msl.mm b/src/libutils/oglapphelpers/msl.mm index 170062968e..3923b809a1 100644 --- a/src/libutils/oglapphelpers/msl.mm +++ b/src/libutils/oglapphelpers/msl.mm @@ -75,9 +75,8 @@ void RGB_to_RGBA(const float* lutValues, int valueCount, std::vector& flo throw Exception("Missing texture data"); } - // MTLPixelFormatRGB32Float not supported on metal. Adapt to MTLPixelFormatRGBA32Float std::vector float4AdaptedLutValues; - RGB_to_RGBA(lutValues, 3*edgelen*edgelen*edgelen, float4AdaptedLutValues); + memcpy(float4AdaptedLutValues.data(), lutValues, 4 * edgelen*edgelen*edgelen * sizeof(float)); MTLTextureDescriptor* texDescriptor = [MTLTextureDescriptor new]; @@ -123,7 +122,8 @@ void RGB_to_RGBA(const float* lutValues, int valueCount, std::vector& flo } else { - RGB_to_RGBA(values, 3*width*height, adaptedLutValues); + adaptedLutValues.resize(4 * width * height); + memcpy(adaptedLutValues.data(), values, 4 * width * height * sizeof(float)); } MTLTextureDescriptor* texDescriptor = [MTLTextureDescriptor new]; @@ -210,8 +210,9 @@ void RGB_to_RGBA(const float* lutValues, int valueCount, std::vector& flo const char * textureName = nullptr; const char * samplerName = nullptr; unsigned edgelen = 0; + GpuShaderDesc::TextureType channel = GpuShaderDesc::TEXTURE_RGBA_CHANNEL; Interpolation interpolation = INTERP_LINEAR; - m_shaderDesc->get3DTexture(idx, textureName, samplerName, edgelen, interpolation); + m_shaderDesc->get3DTexture(idx, textureName, samplerName, edgelen, channel, interpolation); if(!textureName || !*textureName || !samplerName || !*samplerName diff --git a/tests/cpu/GpuShader_tests.cpp b/tests/cpu/GpuShader_tests.cpp index fa01fef1c2..efc84375c7 100644 --- a/tests/cpu/GpuShader_tests.cpp +++ b/tests/cpu/GpuShader_tests.cpp @@ -122,6 +122,7 @@ OCIO_ADD_TEST(GpuShader, generic_shader) OCIO_CHECK_EQUAL(shaderDesc->getNum3DTextures(), 0U); OCIO_CHECK_NO_THROW(shaderDesc->add3DTexture("lut1", "lut1Sampler", edgelen, + OCIO::GpuShaderDesc::TEXTURE_RGB_CHANNEL, OCIO::INTERP_TETRAHEDRAL, &values[0])); @@ -130,16 +131,18 @@ OCIO_ADD_TEST(GpuShader, generic_shader) const char * textureName = nullptr; const char * samplerName = nullptr; unsigned e = 0; + OCIO::GpuShaderDesc::TextureType channel; OCIO::Interpolation i = OCIO::INTERP_UNKNOWN; - OCIO_CHECK_NO_THROW(shaderDesc->get3DTexture(0, textureName, samplerName, e, i)); + OCIO_CHECK_NO_THROW(shaderDesc->get3DTexture(0, textureName, samplerName, e, channel, i)); OCIO_CHECK_EQUAL(std::string(textureName), "lut1"); OCIO_CHECK_EQUAL(std::string(samplerName), "lut1Sampler"); OCIO_CHECK_EQUAL(edgelen, e); + OCIO_CHECK_EQUAL(OCIO::GpuShaderDesc::TEXTURE_RGB_CHANNEL, channel); OCIO_CHECK_EQUAL(OCIO::INTERP_TETRAHEDRAL, i); - OCIO_CHECK_THROW_WHAT(shaderDesc->get3DTexture(1, textureName, samplerName, e, i), + OCIO_CHECK_THROW_WHAT(shaderDesc->get3DTexture(1, textureName, samplerName, e, channel, i), OCIO::Exception, "3D LUT access error"); @@ -158,6 +161,7 @@ OCIO_ADD_TEST(GpuShader, generic_shader) // Supports several 3D LUTs OCIO_CHECK_NO_THROW(shaderDesc->add3DTexture("lut1", "lut1Sampler", edgelen, + OCIO::GpuShaderDesc::TEXTURE_RGB_CHANNEL, OCIO::INTERP_TETRAHEDRAL, &values[0])); @@ -166,6 +170,7 @@ OCIO_ADD_TEST(GpuShader, generic_shader) // Check the 3D LUT limit OCIO_CHECK_THROW(shaderDesc->add3DTexture("lut1", "lut1Sampler", 130, + OCIO::GpuShaderDesc::TEXTURE_RGB_CHANNEL, OCIO::INTERP_TETRAHEDRAL, &values[0]), OCIO::Exception); diff --git a/tests/osl/UnitTestMain.cpp b/tests/osl/UnitTestMain.cpp index 3a69ed3659..e86e7f0247 100644 --- a/tests/osl/UnitTestMain.cpp +++ b/tests/osl/UnitTestMain.cpp @@ -85,6 +85,7 @@ class MyOSLShaderCreator final : public OCIO::GpuShaderCreator void add3DTexture(const char * /*textureName*/, const char * /*samplerName*/, unsigned /*edgelen*/, + TextureType /*channel*/, OCIO::Interpolation /*interpolation*/, const float * /*values*/) override { diff --git a/tests/python/GpuShaderDescTest.py b/tests/python/GpuShaderDescTest.py index a81dc4c2c1..9ce11deb5d 100644 --- a/tests/python/GpuShaderDescTest.py +++ b/tests/python/GpuShaderDescTest.py @@ -184,11 +184,11 @@ def test_texture_3d(self): buf = np.linspace(0, 1, num=8*3).astype(np.float32) bufTest1 = buf[3] desc.add3DTexture('tex', 'sampler', 2, - OCIO.INTERP_DEFAULT, buf) + OCIO.GpuShaderDesc.TEXTURE_RGB_CHANNEL, OCIO.INTERP_DEFAULT, buf) buf = np.linspace(0, 1, num=27*3).astype(np.float32) bufTest2 = buf[42] desc.add3DTexture('tex2', 'sampler2', 3, - OCIO.INTERP_DEFAULT, buf) + OCIO.GpuShaderDesc.TEXTURE_RGB_CHANNEL, OCIO.INTERP_DEFAULT, buf) textures = desc.get3DTextures() self.assertEqual(len(textures), 2) @@ -197,6 +197,7 @@ def test_texture_3d(self): self.assertEqual(t1.samplerName, 'sampler') self.assertEqual(t1.edgeLen, 2) self.assertEqual(t1.interpolation, OCIO.INTERP_DEFAULT) + self.assertEqual(t1.channel, OCIO.GpuShaderDesc.TEXTURE_RGB_CHANNEL) v1 = t1.getValues() self.assertEqual(len(v1), 3*8) self.assertEqual(v1[3], bufTest1) @@ -205,6 +206,7 @@ def test_texture_3d(self): self.assertEqual(t2.samplerName, 'sampler2') self.assertEqual(t2.edgeLen, 3) self.assertEqual(t2.interpolation, OCIO.INTERP_DEFAULT) + self.assertEqual(t2.channel, OCIO.GpuShaderDesc.TEXTURE_RGB_CHANNEL) v2 = t2.getValues() self.assertEqual(len(v2), 3*27) self.assertEqual(v2[42], bufTest2)