Skip to content

Commit 898a1c5

Browse files
Support for 3D (unsigned) integer textures and fix for importing RGB PNGs via Java2D
1 parent 9551b27 commit 898a1c5

File tree

1 file changed

+153
-79
lines changed

1 file changed

+153
-79
lines changed

src/main/java/cleargl/GLTexture.java

Lines changed: 153 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
import java.util.Arrays;
1414
import java.util.Hashtable;
1515
import javax.imageio.ImageIO;
16-
import com.jogamp.opengl.GL;
17-
import com.jogamp.opengl.GL2ES2;
1816
import com.jogamp.opengl.GL4;
1917
import com.jogamp.opengl.GLException;
2018

@@ -132,63 +130,81 @@ public GLTexture(final GL4 pGL,
132130
mTextureDepth = pTextureDepth;
133131
mMipMapLevels = pMipMapLevels;
134132

135-
mTextureTarget = mTextureDepth == 1 ? GL.GL_TEXTURE_2D
136-
: GL2ES2.GL_TEXTURE_3D;
137-
mTextureOpenGLFormat = mNumberOfChannels == 4 ? GL.GL_RGBA// GL_BGRA
138-
: GL2ES2.GL_RED;
133+
mTextureTarget = mTextureDepth == 1 ? GL4.GL_TEXTURE_2D
134+
: GL4.GL_TEXTURE_3D;
135+
switch(mNumberOfChannels) {
136+
case 1:
137+
if(mType == GLTypeEnum.UnsignedShort) {
138+
mTextureOpenGLFormat = GL4.GL_RED_INTEGER;
139+
} else {
140+
mTextureOpenGLFormat = GL4.GL_RED;
141+
}
142+
break;
143+
case 2:
144+
if(mType == GLTypeEnum.UnsignedByte) {
145+
mTextureOpenGLFormat = GL4.GL_RG_INTEGER;
146+
} else {
147+
mTextureOpenGLFormat = GL4.GL_RG;
148+
}
149+
break;
150+
case 3:
151+
if(mType == GLTypeEnum.UnsignedByte) {
152+
mTextureOpenGLFormat = GL4.GL_RGB_INTEGER;
153+
} else {
154+
mTextureOpenGLFormat = GL4.GL_RGB;
155+
}
156+
break;
157+
case 4:
158+
default:
159+
if(mType == GLTypeEnum.UnsignedByte) {
160+
mTextureOpenGLFormat = GL4.GL_RGBA_INTEGER;
161+
} else {
162+
mTextureOpenGLFormat = GL4.GL_RGBA;
163+
}
164+
}
139165

140166
mTextureOpenGLDataType = mType.glType();
141167
if (mType == GLTypeEnum.Byte) {
142-
mTextureOpenGLInternalFormat = mNumberOfChannels == 4 ? GL.GL_RGBA8
143-
: GL.GL_R8;
144168
switch (mNumberOfChannels) {
145169
case 1:
146-
mTextureOpenGLInternalFormat = GL.GL_R8;
170+
mTextureOpenGLInternalFormat = GL4.GL_R8;
147171
break;
148172
case 2:
149-
mTextureOpenGLInternalFormat = GL.GL_RG8;
173+
mTextureOpenGLInternalFormat = GL4.GL_RG8;
150174
break;
151175
case 3:
152-
mTextureOpenGLInternalFormat = GL.GL_RGB8;
176+
mTextureOpenGLInternalFormat = GL4.GL_RGB8;
153177
break;
154178
case 4:
155-
mTextureOpenGLInternalFormat = GL.GL_RGBA8;
179+
mTextureOpenGLInternalFormat = GL4.GL_RGBA8;
156180
break;
157181
default:
158-
mTextureOpenGLInternalFormat = GL.GL_RGBA8;
182+
mTextureOpenGLInternalFormat = GL4.GL_RGBA8;
159183
}
160184
mBytesPerChannel = 1;
161185
} else if (mType == GLTypeEnum.UnsignedByte) {
162186
switch (mNumberOfChannels) {
163187
case 1:
164-
mTextureOpenGLInternalFormat = GL.GL_R8;
188+
mTextureOpenGLInternalFormat = GL4.GL_R8;
165189
break;
166190
case 2:
167-
mTextureOpenGLInternalFormat = GL.GL_RG8;
191+
mTextureOpenGLInternalFormat = GL4.GL_RG8;
168192
break;
169193
case 3:
170-
mTextureOpenGLInternalFormat = GL.GL_RGB8;
194+
mTextureOpenGLInternalFormat = GL4.GL_RGB8;
171195
break;
172196
case 4:
173-
mTextureOpenGLInternalFormat = GL.GL_RGBA8;
197+
mTextureOpenGLInternalFormat = GL4.GL_RGBA8;
174198
break;
175199
default:
176-
mTextureOpenGLInternalFormat = GL.GL_RGBA8;
200+
mTextureOpenGLInternalFormat = GL4.GL_RGBA8;
177201
}
178202
mBytesPerChannel = 1;
179203
} else if (mType == GLTypeEnum.Short) {
180-
mTextureOpenGLInternalFormat = mNumberOfChannels == 4 ? GL.GL_RGBA16F
181-
: GL.GL_R16F;
204+
mTextureOpenGLInternalFormat = mNumberOfChannels == 4 ? GL4.GL_RGBA16F
205+
: GL4.GL_R16F;
182206
mBytesPerChannel = 2;
183207
} else if (mType == GLTypeEnum.UnsignedShort) {
184-
mTextureOpenGLInternalFormat = mNumberOfChannels == 4 ? GL.GL_RGBA16F
185-
: GL.GL_R16F;
186-
mBytesPerChannel = 2;
187-
} else if (mType == GLTypeEnum.Int) {
188-
mTextureOpenGLInternalFormat = mNumberOfChannels == 4 ? GL.GL_RGBA32F
189-
: GL.GL_R32F;
190-
mBytesPerChannel = 4;
191-
} else if (mType == GLTypeEnum.UnsignedInt) {
192208
switch(mNumberOfChannels) {
193209
case 1:
194210
mTextureOpenGLInternalFormat = GL4.GL_R16UI;
@@ -205,44 +221,65 @@ public GLTexture(final GL4 pGL,
205221
}
206222

207223
mBytesPerChannel = 2;
224+
} else if (mType == GLTypeEnum.Int) {
225+
mTextureOpenGLInternalFormat = mNumberOfChannels == 4 ? GL4.GL_RGBA32F
226+
: GL4.GL_R32F;
227+
mBytesPerChannel = 4;
228+
} else if (mType == GLTypeEnum.UnsignedInt) {
229+
switch(mNumberOfChannels) {
230+
case 1:
231+
mTextureOpenGLInternalFormat = GL4.GL_R32UI;
232+
break;
233+
case 2:
234+
mTextureOpenGLInternalFormat = GL4.GL_RG32UI;
235+
break;
236+
case 3:
237+
mTextureOpenGLInternalFormat = GL4.GL_RGB32UI;
238+
break;
239+
case 4:
240+
default:
241+
mTextureOpenGLInternalFormat = GL4.GL_RGBA32UI;
242+
}
243+
244+
mBytesPerChannel = 4;
208245
} else if (mType == GLTypeEnum.Float) {
209246
switch (mNumberOfChannels) {
210247
case 1:
211-
mTextureOpenGLInternalFormat = GL.GL_R32F;
248+
mTextureOpenGLInternalFormat = GL4.GL_R32F;
212249
mBytesPerChannel = 4;
213250
break;
214251
case 2:
215252
if(precision == 16) {
216-
mTextureOpenGLInternalFormat = GL.GL_RG16F;
253+
mTextureOpenGLInternalFormat = GL4.GL_RG16F;
217254
mBytesPerChannel = 4;
218255
} else if(precision == 32) {
219-
mTextureOpenGLInternalFormat = GL.GL_RG32F;
256+
mTextureOpenGLInternalFormat = GL4.GL_RG32F;
220257
mBytesPerChannel = 4;
221258
}
222259
case 3:
223260
if (precision == 16) {
224-
mTextureOpenGLInternalFormat = GL.GL_RGB16F;
261+
mTextureOpenGLInternalFormat = GL4.GL_RGB16F;
225262
mBytesPerChannel = 4;
226263
} else if (precision == 32) {
227-
mTextureOpenGLInternalFormat = GL.GL_RGB32F;
264+
mTextureOpenGLInternalFormat = GL4.GL_RGB32F;
228265
mBytesPerChannel = 4;
229266
}
230267
break;
231268
case 4:
232269
if (precision == 16) {
233-
mTextureOpenGLInternalFormat = GL.GL_RGBA16F;
270+
mTextureOpenGLInternalFormat = GL4.GL_RGBA16F;
234271
mBytesPerChannel = 4;
235272
} else {
236-
mTextureOpenGLInternalFormat = GL.GL_RGBA32F;
273+
mTextureOpenGLInternalFormat = GL4.GL_RGBA32F;
237274
mBytesPerChannel = 4;
238275
}
239276
break;
240277
case -1:
241278
if (precision == 24) {
242-
mTextureOpenGLInternalFormat = GL.GL_DEPTH_COMPONENT24;
279+
mTextureOpenGLInternalFormat = GL4.GL_DEPTH_COMPONENT24;
243280
mBytesPerChannel = 3;
244281
} else {
245-
mTextureOpenGLInternalFormat = GL.GL_DEPTH_COMPONENT32;
282+
mTextureOpenGLInternalFormat = GL4.GL_DEPTH_COMPONENT32;
246283
mBytesPerChannel = 4;
247284
}
248285
break;
@@ -252,30 +289,47 @@ public GLTexture(final GL4 pGL,
252289

253290
mGL.glGenTextures(1, mTextureId, 0);
254291
bind();
255-
mGL.glTexParameterf(mTextureTarget,
256-
GL.GL_TEXTURE_MAG_FILTER,
257-
pLinearInterpolation ? GL.GL_LINEAR
258-
: GL.GL_NEAREST);
259-
mGL.glTexParameterf(mTextureTarget,
260-
GL.GL_TEXTURE_MIN_FILTER,
261-
mMipMapLevels > 1 ? (pLinearInterpolation ? GL.GL_LINEAR_MIPMAP_LINEAR
262-
: GL.GL_NEAREST_MIPMAP_NEAREST)
263-
: (pLinearInterpolation ? GL.GL_LINEAR
264-
: GL.GL_NEAREST));
265-
mGL.glTexParameterf(mTextureTarget,
266-
GL.GL_TEXTURE_WRAP_S,
267-
GL.GL_REPEAT);
268-
mGL.glTexParameterf(mTextureTarget,
269-
GL.GL_TEXTURE_WRAP_T,
270-
GL.GL_REPEAT);
271292

272-
if (mTextureDepth == 1) {
293+
if(mTextureTarget == GL4.GL_TEXTURE_2D) {
294+
mGL.glTexParameteri(mTextureTarget,
295+
GL4.GL_TEXTURE_MAG_FILTER,
296+
pLinearInterpolation ? GL4.GL_LINEAR
297+
: GL4.GL_NEAREST);
298+
mGL.glTexParameteri(mTextureTarget,
299+
GL4.GL_TEXTURE_MIN_FILTER,
300+
mMipMapLevels > 1 ? (pLinearInterpolation ? GL4.GL_LINEAR_MIPMAP_LINEAR
301+
: GL4.GL_NEAREST_MIPMAP_NEAREST)
302+
: (pLinearInterpolation ? GL4.GL_LINEAR
303+
: GL4.GL_NEAREST));
304+
mGL.glTexParameteri(mTextureTarget,
305+
GL4.GL_TEXTURE_WRAP_S,
306+
GL4.GL_REPEAT);
307+
mGL.glTexParameteri(mTextureTarget,
308+
GL4.GL_TEXTURE_WRAP_T,
309+
GL4.GL_REPEAT);
310+
273311
mGL.glTexStorage2D(mTextureTarget,
274312
mMipMapLevels,
275313
mTextureOpenGLInternalFormat,
276314
mTextureWidth,
277315
mTextureHeight);
278316
} else {
317+
mGL.glTexParameteri(mTextureTarget,
318+
GL4.GL_TEXTURE_MIN_FILTER,
319+
GL4.GL_NEAREST);
320+
mGL.glTexParameteri(mTextureTarget,
321+
GL4.GL_TEXTURE_MAG_FILTER,
322+
GL4.GL_NEAREST);
323+
mGL.glTexParameteri(mTextureTarget,
324+
GL4.GL_TEXTURE_WRAP_S,
325+
GL4.GL_CLAMP_TO_EDGE);
326+
mGL.glTexParameteri(mTextureTarget,
327+
GL4.GL_TEXTURE_WRAP_T,
328+
GL4.GL_CLAMP_TO_EDGE);
329+
mGL.glTexParameteri(mTextureTarget,
330+
GL4.GL_TEXTURE_WRAP_R,
331+
GL4.GL_CLAMP_TO_EDGE);
332+
279333
mGL.glTexStorage3D(mTextureTarget,
280334
1,
281335
mTextureOpenGLInternalFormat,
@@ -328,44 +382,59 @@ public void bind(final GLProgram pGLProgram) {
328382
}
329383

330384
public void bind() {
331-
mGL.glActiveTexture(GL.GL_TEXTURE0);
385+
mGL.glActiveTexture(GL4.GL_TEXTURE0);
332386
mGL.glBindTexture(mTextureTarget, getId());
333387
}
334388

335389
public void bind(final int pTextureUnit) {
336-
mGL.glActiveTexture(GL.GL_TEXTURE0 + pTextureUnit);
390+
mGL.glActiveTexture(GL4.GL_TEXTURE0 + pTextureUnit);
337391
mGL.glBindTexture(mTextureTarget, getId());
338392
}
339393

340394
public void setClamp(final boolean clampS, final boolean clampT) {
341395
mGL.glTexParameterf(mTextureTarget,
342-
GL.GL_TEXTURE_WRAP_S,
343-
clampS ? GL.GL_CLAMP_TO_EDGE : GL.GL_REPEAT);
396+
GL4.GL_TEXTURE_WRAP_S,
397+
clampS ? GL4.GL_CLAMP_TO_EDGE : GL4.GL_REPEAT);
344398
mGL.glTexParameterf(mTextureTarget,
345-
GL.GL_TEXTURE_WRAP_T,
346-
clampT ? GL.GL_CLAMP_TO_EDGE : GL.GL_REPEAT);
399+
GL4.GL_TEXTURE_WRAP_T,
400+
clampT ? GL4.GL_CLAMP_TO_EDGE : GL4.GL_REPEAT);
347401
}
348402

349403
public void clear() {
350404
bind();
351405

352406
final int lNeededSize = mTextureWidth * mTextureHeight
407+
* mTextureDepth
353408
* mBytesPerChannel
354409
* mNumberOfChannels;
355410

356411
// empty buffer
357412
final Buffer lEmptyBuffer = ByteBuffer.allocateDirect(lNeededSize)
358413
.order(ByteOrder.nativeOrder());
359414

360-
mGL.glTexSubImage2D(mTextureTarget,
361-
0,
362-
0,
363-
0,
364-
mTextureWidth,
365-
mTextureHeight,
366-
mTextureOpenGLFormat,
367-
mTextureOpenGLDataType,
368-
lEmptyBuffer);
415+
if(mTextureTarget == GL4.GL_TEXTURE_2D) {
416+
mGL.glTexSubImage2D(mTextureTarget,
417+
0,
418+
0,
419+
0,
420+
mTextureWidth,
421+
mTextureHeight,
422+
mTextureOpenGLFormat,
423+
mTextureOpenGLDataType,
424+
lEmptyBuffer);
425+
} else {
426+
mGL.glTexSubImage3D(mTextureTarget,
427+
0,
428+
0,
429+
0,
430+
0,
431+
mTextureWidth,
432+
mTextureHeight,
433+
mTextureDepth,
434+
mTextureOpenGLFormat,
435+
mTextureOpenGLDataType,
436+
lEmptyBuffer);
437+
}
369438
if (mMipMapLevels > 1)
370439
updateMipMaps();
371440

@@ -399,7 +468,7 @@ public void copyFrom(final Buffer pBuffer,
399468
bind();
400469
pBuffer.rewind();
401470

402-
if(mTextureDepth == 1) {
471+
if(mTextureTarget == GL4.GL_TEXTURE_2D) {
403472
mGL.glTexSubImage2D(mTextureTarget,
404473
pLODLevel,
405474
0,
@@ -423,8 +492,9 @@ public void copyFrom(final Buffer pBuffer,
423492
pBuffer);
424493
}
425494

426-
if (pAutoGenerateMipMaps && mMipMapLevels > 1)
495+
if (pAutoGenerateMipMaps && mMipMapLevels > 1 && mTextureTarget == GL4.GL_TEXTURE_2D) {
427496
updateMipMaps();
497+
}
428498
}
429499

430500
public void copyFrom(final Buffer pBuffer) {
@@ -473,8 +543,8 @@ public int getBitsPerChannel() {
473543
}
474544

475545
@Override
476-
public GL getGL() {
477-
return mGL.getGL();
546+
public GL4 getGL() {
547+
return mGL.getGL().getGL4();
478548
}
479549

480550
@Override
@@ -549,12 +619,9 @@ public static GLTexture loadFromFile(final GL4 gl, final String filename, final
549619
} else {
550620
try {
551621
fis = new FileInputStream(filename);
552-
channel = fis.getChannel();
553-
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
554-
channel.transferTo(0, channel.size(), Channels.newChannel(byteArrayOutputStream));
555-
bi = ImageIO.read(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
622+
bi = ImageIO.read(fis);
623+
fis.close();
556624

557-
channel.close();
558625
} catch (final Exception e) {
559626
System.err.println("GLTexture: could not read image from " + filename + ".");
560627
return null;
@@ -581,9 +648,16 @@ public static GLTexture loadFromFile(final GL4 gl, final String filename, final
581648
levels = 1;
582649
}
583650

651+
int channelCount = bi.getColorModel().getNumComponents();
652+
653+
// work around a Java2D issue
654+
if(channelCount == 3 && filename.substring(filename.lastIndexOf(".")).toLowerCase().endsWith("png")) {
655+
channelCount = 4;
656+
}
657+
584658
tex = new GLTexture(gl,
585659
nativeTypeEnumFromBufferedImage(bi),
586-
bi.getColorModel().getNumComponents(),
660+
channelCount,
587661
texWidth, texHeight, 1,
588662
linearInterpolation,
589663
levels);

0 commit comments

Comments
 (0)