@@ -48,6 +48,11 @@ void CreatePaddedLutChannels(unsigned long width,
4848 leftover -= step;
4949 }
5050
51+ // Skip the duplicate entry if the last value is the last pixel on a row
52+ if ((currWidth + (height -1 )) % width == 0 ) {
53+ leftover -= 1 ;
54+ }
55+
5156 // If there are still texels to fill, add them to the texture data.
5257 if (leftover > 0 )
5358 {
@@ -111,6 +116,11 @@ void CreatePaddedRedChannel(unsigned long width,
111116 leftover -= step;
112117 }
113118
119+ // Skip the duplicate entry if the last value is the last pixel on a row
120+ if ((currWidth + (height -1 )) % width == 0 ) {
121+ leftover -= 1 ;
122+ }
123+
114124 // If there are still texels to fill, add them to the texture data.
115125 if (leftover > 0 )
116126 {
@@ -154,13 +164,27 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
154164
155165 const unsigned long length = lutData->getArray ().getLength ();
156166 const unsigned long width = std::min (length, defaultMaxWidth);
157- const unsigned long height = (length / defaultMaxWidth) + 1 ;
167+ const unsigned long heightWithDuplicates = (length - 1 ) / (defaultMaxWidth - 1 ) + 1 ;
168+
169+ // The height is calculated based on the amount of rows without duplicate data.
170+ // ceil(length / defaultMaxWidth)
171+ const unsigned long heightWithoutDuplicates = (std::max (2UL , length) - 1 ) / defaultMaxWidth + 1 ;
172+
173+ // The result of this determines how many duplicate values are really needed.
174+ // When the amount of rows is one, the amount of duplicate entries will be zero.
175+ // ceil(length / defaultMaxWidth) -1)
176+ const unsigned long numDuplicateEntries = heightWithoutDuplicates - 1 ;
177+
178+ // Once we know the amount of duplicate entries, we can calculate if the last
179+ // value ends on the same scanline, if that is the case we won't need an extra line.
180+ // ((ceil(length / defaultMaxWidth) -1 + length) % defaultMaxWidth == 0)
181+ const unsigned long height = heightWithDuplicates - ((numDuplicateEntries + length) % defaultMaxWidth == 0 );
158182 const unsigned long numChannels = lutData->getArray ().getNumColorComponents ();
159183
160- // Note: The 1D LUT needs a GPU texture for the Look-up table implementation.
184+ // Note: The 1D LUT needs a GPU texture for the Look-up table implementation.
161185 // However, the texture type & content may vary based on the number of channels
162186 // i.e. when all channels are identical a F32 Red GPU texture is enough.
163-
187+
164188 const bool singleChannel = (numChannels == 1 );
165189
166190 // Adjust LUT texture to allow for correct 2d linear interpolation, if needed.
@@ -335,13 +359,13 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
335359 {
336360 const std::string str = name + " _computePos(" + shaderCreator->getPixelName ();
337361
338- ss.newLine () << shaderCreator->getPixelName () << " .r = "
362+ ss.newLine () << shaderCreator->getPixelName () << " .r = "
339363 << ss.sampleTex2D (name, str + " .r)" ) << " .r;" ;
340364
341365 ss.newLine () << shaderCreator->getPixelName () << " .g = "
342366 << ss.sampleTex2D (name, str + " .g)" ) << (singleChannel ? " .r;" : " .g;" );
343367
344- ss.newLine () << shaderCreator->getPixelName () << " .b = "
368+ ss.newLine () << shaderCreator->getPixelName () << " .b = "
345369 << ss.sampleTex2D (name, str + " .b)" ) << (singleChannel ? " .r;" : " .b;" );
346370 }
347371 else
@@ -387,4 +411,3 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
387411}
388412
389413} // namespace OCIO_NAMESPACE
390-
0 commit comments