英文:
Skybox textures is transparent
问题
我的天空盒被显示出来了,但是它并没有显示从图像加载的纹理。相反,如果我将 glTexImage2D
设置为 GL_RGBA
,它显示透明颜色;如果我将 glTexImage2D
设置为 GL_RGB
,它显示黑色颜色。
我正在使用带有多重采样帧缓冲支持的渲染器(链接)。
我的纹理加载代码如下:
private int loadSkyboxTextures() {
// ... (代码和注释已省略)
for (int i = 0; i < TEXTURE_FILES.length; i++) {
InputStream file = getClass().getResourceAsStream(TEXTURE_FILES[i]);
byte[] pixelData = new byte[0];
try {
pixelData = new byte[file.available()];
file.read(pixelData);
} catch (IOException e) {
e.printStackTrace();
}
ByteBuffer byteBuffer = ByteBuffer.wrap(pixelData);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 512, 512, 0,
GL_RGB, GL_UNSIGNED_BYTE, byteBuffer);
}
// ... (代码和注释已省略)
return texID;
}
立方体渲染代码:
private void drawSkybox() {
// ... (代码和注释已省略)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, texId);
glDrawArrays(GL_TRIANGLES, 0, 36);
// ... (代码和注释已省略)
}
主渲染函数中的立方体渲染调用:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
view = viewX || viewY || viewZ;
if (view)
glPushMatrix();
int rot = 180;
glDisable(GL_LIGHTING);
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
// ... (代码和注释已省略)
glRotated(cameraX, 1f, 0f, 0);
glRotated(cameraY, 0f, 1f, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawSkybox(texId);
// ... (代码和注释已省略)
英文:
My skybox is displayed, but does not display the textures that I load from the image. Instead, it shows the transparent color if i set glTexImage2D
how GL_RGBA
, or black color if i set glTexImage2D
how GL_RGB
.
I am using a render with MultisampledFbo support.
My texture loading code looks like this:
private int loadSkyboxTextures(){
glGenBuffers(vbo);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, POINTS, GL_STATIC_DRAW);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glGenVertexArrays(vao);
glBindVertexArray(vao[0]);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glVertexPointer(3, GL_FLOAT, 3 * Float.BYTES, NULL);
glTexCoordPointer (3, GL_FLOAT, 3 * Float.BYTES, NULL);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
int texID = glGenTextures();
glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
for(int i = 0; i < TEXTURE_FILES.length; i++){
InputStream file = getClass().getResourceAsStream(TEXTURE_FILES[i]);
byte[] pixelData = new byte[0];
try {
pixelData = new byte[file.available()];
file.read(pixelData);
} catch (IOException e) {
e.printStackTrace();
}
ByteBuffer byteBuffer = ByteBuffer.wrap(pixelData);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 512, 512, 0,
GL_RGB, GL_UNSIGNED_BYTE, byteBuffer);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
return texID;
}
Cube Render Code:
private void drawSkybox(){
glColor4f(1,1,1,1);
glDepthMask(false);
glEnable(GL_TEXTURE_CUBE_MAP);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glBindVertexArray(vao[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, texId);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glDepthMask(true);
glDisable(GL_TEXTURE_CUBE_MAP);
}
The cube rendering call in the main render function:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
view = viewX || viewY || viewZ;
if(view)
glPushMatrix();
int rot = 180;
glDisable(GL_LIGHTING);
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-max, max, -1, 1, 10, -10);
glRotated(cameraX, 1f, 0f, 0);
glRotated(cameraY, 0f, 1f, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawSkybox(texId);
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
...
//render camera and other objects
答案1
得分: 0
以下是翻译好的内容:
对于立方体贴图纹理,纹理坐标是三维的,并且被视为从立方体贴图的中心指向的向量。
由于绘制的是以 (0, 0, 0) 为中心的立方体,你也可以使用顶点坐标作为纹理坐标。由于你没有使用着色器程序,所以必须使用固定功能属性。通过 glVertexPointer
指定顶点坐标,通过 glTexCoordPointer
指定纹理坐标。通过 glEnableClientState
启用客户端能力 GL_VERTEX_ARRAY
和 GL_TEXTURE_COORD_ARRAY
。
指定顶点数组对象。只需要在初始化时执行该代码一次:
glGenBuffers(vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, POINTS, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenVertexArrays(vao);
glBindVertexArray(vao[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexPointer(3, GL_FLOAT, false, 3 * Float.BYTES, NULL);
glTexCoordPointer(3, GL_FLOAT, false, 3 * Float.BYTES, NULL);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindVertexArray(0);
当绘制天空盒时,只需要绑定立方体贴图纹理以启用立方体贴图,并绑定顶点数组对象(VAO):
private void drawSkybox(){
GL11.glColor4f(1, 1, 1, 1);
glDepthMask(false);
glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
glBindVertexArray(vao[0]);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthMask(true);
glDisable(GL_TEXTURE_CUBE_MAP);
}
还存在一些其他问题:
-
图像没有被正确读取。参见 I have a black texture。
-
在绘制天空盒后清除深度缓冲区。参见 Skybox textures do not display correctly。
英文:
For cube map textures, the texture coordinates are 3-dimensional and treated as a vector form the center of the cube map.
Since you draw a cube, which is centered around (0, 0, 0), you can use the the vertex coordinates for the texture coordinates, too. You do not use a shader program, so you have to use fixed function attributes. Specify the vertex coordinates by glVertexPointer
and the texture coordinates by glTexCoordPointer
. Enable the client-side capability (glEnableClientState
) GL_VERTEX_ARRAY
and GL_TEXTURE_COORD_ARRAY
.
Specify the Vertex Array Object. It is sufficient to execute that code once at intialization:
glGenBuffers(vbo);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, POINTS, GL_STATIC_DRAW);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glGenVertexArrays(vao);
glBindVertexArray(vao[0]);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glVertexPointer(3, GL_FLOAT, false, 3 * Float.BYTES, NULL);
glTexCoordPointer (3, GL_FLOAT, false, 3 * Float.BYTES, NULL);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindVertexArray(0);
When you draw the skybox it is sufficient to bind the cubemap texture to enable cube-mapped texturing and to bind the VAO:
private void drawSkybox(){
GL11.glColor4f(1,1,1,1);
glDepthMask(false);
glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
glBindVertexArray(vao[0]);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthMask(true);
glDisable(GL_TEXTURE_CUBE_MAP);
}
There are some further issues:
-
The image is not read correctly. See I have a black texture.
-
Clear the depth buffer after drawing the skybox. See Skybox textures do not display correctly
专注分享java语言的经验与见解,让所有开发者获益!
评论