我试图使用创建纹理并存储它的ID和大小(感谢ADC和另一个stackoverflow成员)的模型类来渲染2纹理的非幂次,以及创建VBO的附加代码并渲染它(VBO和渲染的代码仅用于测试目的,它在我的模型中被正确划分)。OpenGL纹理初始化/渲染问题
当我使用此代码,但删除纹理特定的代码时,它工作正常。但是,当添加特定于纹理的代码时,它只会渲染我认为是右下像素的图像,从尝试多个复杂图像并使用DigitalColor Meter检查图像和输出。
我不认为使用此设置时必须明确指定纹理坐标,如果他们这样做,我会怎么样?
主要的OpenGL代码
// Create vertex buffer
GLuint memoryPointer = 0;
GLuint colourMemoryPointer = 0;
GLfloat *vertices;
size_t vertex_size = 0;
int check = AllocateVertexBuffer(2, 4, &vertices, &vertex_size);
CDMeshVertexesCreateRectangle(200, 200, vertices);
// Create colour buffer
GLfloat *colors;
size_t color_size;
int check2 = AllocateVertexBuffer(4, 4, &colors, &color_size);
CDMeshColorsCreateGrey(1.0, 4, colors);
// Create texture buffer
CDTexture *texture = [CDTexture loadPngTexture:@"Rawr"];
// Allocate the buffer
glGenBuffers(1, &memoryPointer);
// Bind the buffer object (tell OpenGL what to use)
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
// Allocate space for the VBO
glBufferData(GL_ARRAY_BUFFER, vertex_size, vertices, GL_STATIC_DRAW);
// Allocate the buffer
glGenBuffers(1, &colourMemoryPointer);
// Bind the buffer object (tell OpenGL what to use)
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
// Allocate space for the VBO
glBufferData(GL_ARRAY_BUFFER, color_size, colors, GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY); // Activate vertex coordinates array
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture.ID);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
//[texture render];
//render
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY); // Deactivate vertex coordinates array
glDisableClientState(GL_COLOR_ARRAY);
free(vertices);
free(colors);
CDTexture loadPngTexture:方法
CFURLRef textureURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
(CFStringRef)fileName,
CFSTR("png"),
NULL);
NSAssert(textureURL, @"Texture name invalid");
// Get the image source using a file path
CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(textureURL, NULL);
NSAssert(myImageSourceRef, @"Invalid Image Path.");
NSAssert((CGImageSourceGetCount(myImageSourceRef) > 0), @"No Image in Image Source.");
// Get the image reference using the source reference, -_-
CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL);
NSAssert(myImageSourceRef, @"Image not created.");
// Start gathering data from the image, before releasing it
GLuint myTextureName;
size_t width = CGImageGetWidth(myImageRef);
size_t height = CGImageGetHeight(myImageRef);
CGRect rect = {{0, 0}, {width, height}};
void * myData = calloc(width * 4, height);
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGContextRef myBitmapContext = CGBitmapContextCreate (myData,
width, height, 8,
width*4, space,
kCGBitmapByteOrder32Host |
kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(space);
// Flip so that it isn't upside-down
CGContextTranslateCTM(myBitmapContext, 0, height);
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
CGContextSetBlendMode(myBitmapContext, kCGBlendModeCopy);
CGContextDrawImage(myBitmapContext, rect, myImageRef);
CGContextRelease(myBitmapContext);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
// Generate texture buffer
glGenTextures(1, &myTextureName);
// Bind buffer for use
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
// Set storage methods
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Set the parameter required for non power of two textures
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Load the texture data into the buffer
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, width, height,
0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, myData);
// Free the data used, as it's now in the buffer
free(myData);
// Return information on texture object
CDTexture *texture = [[CDTexture alloc] init];
texture.ID = myTextureName;
texture.size = NSMakeSize(width, height);
return texture;
UPDATE
我使用一个纹理指针定义区域尝试,而这导致了同样的问题。即使没有绑定和使用指针,它绘制的颜色/纹理也会这样做。我也曾尝试在使用和渲染之前和之后启用和禁用GL_TEXTURE_COORD_ARRAY,并导致相同的问题。
除非我做错了什么,这个问题似乎与纹理指针没有关系。
GLfloat texCoords[8] = {
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
1.0, 0.0
};
...
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture.ID);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
//[texture render];
//render
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
更新2
我试图获得来自OpenGL的错误代码,试图解决这个问题,但没有错误代码已被打印出来。
UPDATE 3
我已使用不同的方法来获得原始图像数据试过,和相同的结果发生(尽管有一些变色,因为我不能使用正确的颜色设置)。 OpenGL对这些数据的解释在这里必须是有缺陷的。我已经尝试过使用glPixelStorei(),但到目前为止没有任何改变。由于OpenGL没有报告任何错误,它必须与数据的程序解释一致,所以无论是我为存储数据的方式设置的参数,还是只导致1像素显示的顶点问题,虽然由于这个原因精度,它很可能是参数。
原始图像数据的新过程(感谢另一个stackoverflow用户)。发布供参考。
NSBitmapImageRep *theImage;
int bitsPPixel, bytesPRow;
NSSize size;
unsigned char *theImageData;
NSData* imgData = [NSData dataWithContentsOfFile:fileName options:NSUncachedRead error:nil]; // use FileURL
theImage = [NSBitmapImageRep imageRepWithData:imgData];
if(theImage != nil)
{
bitsPPixel = [theImage bitsPerPixel];
bytesPRow = [theImage bytesPerRow];
size.width = [theImage pixelsWide];
size.height = [theImage pixelsHigh];
}
enter code here
UPDATE 4
更改为GL_TEXTURE_2D效率。左下角的像素仍然只能被渲染。这里是代码的完整的订单:
// Create vertex buffer
GLuint memoryPointer = 0;
GLuint colourMemoryPointer = 0;
GLfloat *vertices;
size_t vertex_size = 0;
AllocateVertexBuffer(2, 4, &vertices, &vertex_size);
CDMeshVertexesCreateRectangle(200, 200, vertices);
// Create colour buffer
GLfloat *colors;
size_t color_size;
AllocateVertexBuffer(4, 4, &colors, &color_size);
CDMeshColorsCreateGrey(1.0, 4, colors);
// Create Texture UV Coordinates
GLfloat *texture;
size_t texture_size;
AllocateVertexBuffer(4, 2, &texture, &texture_size);
CDMeshVertexesCreateRectangle(1, 1, texture);
// Create texture buffer
NSString *fileName = @"Rawr3";
CFURLRef textureURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
(CFStringRef)fileName,
CFSTR("png"),
NULL);
NSAssert(textureURL, @"Texture name invalid");
// Get the image source using a file path
CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(textureURL, NULL);
NSAssert(myImageSourceRef, @"Invalid Image Path.");
NSAssert((CGImageSourceGetCount(myImageSourceRef) > 0), @"No Image in Image Source.");
// Get the image reference using the source reference, -_-
CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL);
NSAssert(myImageSourceRef, @"Image not created.");
// Start gathering data from the image, before releasing it
GLuint myTextureName;
size_t width = CGImageGetWidth(myImageRef);
size_t height = CGImageGetHeight(myImageRef);
CGRect rect = {{0, 0}, {width, height}}; //Doesnt need fiddling
void * myData = calloc(width * 4, height); //Fiddled
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGContextRef myBitmapContext = CGBitmapContextCreate (myData,
width, height, 8,
width*4, space,
kCGBitmapByteOrder32Host |
kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(space);
// Flip so that it isn't upside-down
CGContextTranslateCTM(myBitmapContext, 0, height);
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
CGContextSetBlendMode(myBitmapContext, kCGBlendModeCopy);
CGContextDrawImage(myBitmapContext, rect, myImageRef);
CGContextRelease(myBitmapContext);
// Generate texture buffer
glGenTextures(1, &myTextureName);
// Bind buffer for use
glBindTexture(GL_TEXTURE_2D, myTextureName);
// Set storage methods
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_STORAGE_HINT_APPLE,
GL_STORAGE_CACHED_APPLE);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
// Set clamping and rendering preferences
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
// Load the texture data into the buffer
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, myData);
glGetError();
// Free the data used, as it's now in the buffer
free(myData);
// Return information on texture object
CDTexture *textureObj = [[CDTexture alloc] init];
textureObj.ID = myTextureName;
textureObj.size = NSMakeSize(width, height);
// Allocate the buffer
glGenBuffers(1, &memoryPointer);
// Bind the buffer object (tell OpenGL what to use)
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
// Allocate space for the VBO
glBufferData(GL_ARRAY_BUFFER, vertex_size, vertices, GL_STATIC_DRAW);
// Allocate the buffer
glGenBuffers(1, &colourMemoryPointer);
// Bind the buffer object (tell OpenGL what to use)
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
// Allocate space for the VBO
glBufferData(GL_ARRAY_BUFFER, color_size, colors, GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY); // Activate vertex coordinates array
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindTexture(GL_TEXTURE_2D, textureObj.ID);
glTexCoordPointer(2, GL_FLOAT, 0, texture);
GetGLError();
//render
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY); // Deactivate vertex coordinates array
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glDeleteBuffers(1, &memoryPointer);
glDeleteBuffers(1, &colourMemoryPointer);
GLuint texID = textureObj.ID;
glDeleteBuffers(1, &texID);
free(vertices);
free(colors);
free(texture);
}
UPDATE 5 从glTexImage2D(),它会使纹理的左下像素,即使我不绑定纹理,并添加坐标它,这似乎很奇怪,考虑到它应该使用glTexCoordPointer()绘制。
UPDATE 6 可能是最后更新,所使用的纹理初始化代码与另一更大,“手动”绘图技术和它工作得很好。我已经删除了Apple特定的元素。从该代码中删除颜色VBO和指针时,由于某种奇怪的原因,白色框仍然呈现。问题是与VBO的,但我不明白为什么。 GL_TEXTURE_RECTANGLE_ARB现在仅用于我的彩色纹理,将在解决此问题时更改。
// Create vertex buffer
GLuint memoryPointer = 0;
GLuint colourMemoryPointer = 0;
GLfloat *vertices;
size_t vertex_size = 0;
AllocateVertexBuffer(2, 4, &vertices, &vertex_size);
CDMeshVertexesCreateRectangle(200, 200, vertices);
GetGLError();
// Create colour buffer
GLfloat *colors;
size_t color_size;
AllocateVertexBuffer(4, 4, &colors, &color_size);
CDMeshColorsCreateGrey(0.4, 4, colors);
// Allocate the buffer
glGenBuffers(1, &memoryPointer);
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glBufferData(GL_ARRAY_BUFFER, vertex_size, vertices, GL_STATIC_DRAW);
// Allocate the buffer
glGenBuffers(1, &colourMemoryPointer);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glBufferData(GL_ARRAY_BUFFER, color_size, colors, GL_STATIC_DRAW);
// Enable client states for drawing the various arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Bind each buffer and use the VBO's to draw (apart from the texture buffer)
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName); //
glTexCoordPointer(2, GL_FLOAT, 0, texture);
//render
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// Disale client states as were done with them.
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
GetGLError();
// Delete buffers to avoid problems
glDeleteBuffers(1, &memoryPointer);
glDeleteBuffers(1, &colourMemoryPointer);
glDeleteBuffers(1, &myTextureName);
free(vertices);
free(colors);
free(texture);
提示:不要使用GL_TEXTURE_RECTANGLE_ARB,它不适用于所有gfx卡片及其超级流氓软件,并且不支持mipmapping无论是。总是使用GL_TEXTURE_2D! – Rookie
@Rookie,谢谢你的提示,我已经尝试过使用这个功能的两个图像和UV坐标集,它现在根本不输出图像。虽然会继续使用GL_TEXTURE_2D。 – Croc