[英]Distortion with 'pixel accurate' OpenGL rendering of sprites
定义我要执行的操作:我希望能够从^ 2x ^ 2大小的PNG中获取任意的“ sprite”图像,并仅在屏幕上给定的x / y位置显示感兴趣的像素。
我的结果是问题-严重失真 -看起来糟透了! (请注意,这些SS位于iPhone sim中,但在实际的视网膜设备上,它们看起来是相同的。.junky)。 这是“预览”中源PNG的屏幕截图- 看起来很棒 (我在这个问题中描述的渲染变化几乎完全像垃圾一样)
以前,我曾问过一个有关使用OpenGL ES 2.0将非2幂纹理显示为精灵的问题(尽管这适用于所有OpenGL)。 我已经接近了,但是有一些我无法解决的问题。 我认为可能存在多个错误-我认为存在一些错误,基本上是通过渲染大尺寸然后挤压x2来反方向显示别名,反之亦然,但我看不到。 此外,有一个错误,我无法解决它们。 我无法从视觉上识别它们的发生,但我确定它们在那里。
我正在960 x 640的风景下工作 (在iPhone4视网膜显示屏上)。 所以我希望0-> 959从左到右移动,0-> 639从下到上移动。 (我想我看到的与此相反-但这不是这个问题的意思)
为了使事情变得容易,我在此测试用例中尝试实现的是PNG文件的全屏960x640显示。 只是其中之一。 我先显示红色背景,这样一来,无论是否覆盖屏幕,都很明显。
更新:我意识到setFramebuffer调用中的'glViewport'正在向后设置我的宽度和高度。 我注意到了这一点,因为当我将几何图形设置为从0,0绘制到100,100时,它绘制的是矩形而不是正方形。 当我交换这些时,该调用会绘制一个正方形。 但是,使用相同的调用,我的整个屏幕都充满了0,0-> 480,320(半个“分辨率”)的顶点范围。 但是,无论我从哪里继续前进,我都仍然无法获得令人满意的结果
这是我的顶点着色器:
attribute vec4 a_position;
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
// Gives 'landscape' full screen..
mat4 projectionMatrix = mat4( 2.0/640.0, 0.0, 0.0, -1.0,
0.0, 2.0/960.0, 0.0, -1.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
// Gives a 1/4 of screen.. (not doing 2.0/.. was suggested in previous SO Q)
/*mat4 projectionMatrix = mat4( 1.0/640.0, 0.0, 0.0, -1.0,
0.0, 1.0/960.0, 0.0, -1.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0); */
// Apply the projection matrix to the position and pass the texCoord
void main()
{
gl_Position = a_position;
gl_Position *= projectionMatrix;
v_texCoord = a_texCoord;
}
这是我的片段着色器:
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main()
{
gl_FragColor = texture2D(s_texture, v_texCoord);
}
这是我的绘画代码:
#define MYWIDTH 960.0f
#define MYHEIGHT 640.0f
// I have to refer to 'X' as height although I'd assume I use 'Y' here..
// I think my X and Y throughout this whole block of code is screwed up
// But, I have experimented flipping them all and verifying that if they
// Are taken from the way they're set now to swapping X and Y that things
// end up being turned the wrong way. So this is a mess, but unlikely my problem
#define BG_X_ORIGIN 0.0f
// ALSO NOTE HERE: I have to put my 'dest' at 640.0f.. --- see note [1] below
#define BG_X_DEST 640.0f
#define BG_Y_ORIGIN 0.0f
// --- see note [1] below
#define BG_Y_DEST 960.0f
// These are texturing coordinates, I texture starting at '0' px and then
// I calculate a percentage of the texture to use based on how many pixels I use
// divided by the actual size of the image (1024x1024)
#define BG_X_ZERO 0.0f
#define BG_Y_USEPERCENTAGE BG_X_DEST / 1023.0f
#define BG_Y_ZERO 0.0f
#define BG_X_USEPERCENTAGE BG_Y_DEST / 1023.0f
// glViewport(0, 0, MYWIDTH, MYHEIGHT);
// See note 2.. it sets glViewport basically, provided by Xcode project template
[(EAGLView *)self.view setFramebuffer];
// Big hack just to get things going - like I said before, these could be backwards
// w/respect to X and Y
static const GLfloat backgroundVertices[] = {
BG_X_ORIGIN, BG_Y_ORIGIN,
BG_X_DEST, BG_Y_ORIGIN,
BG_X_ORIGIN, BG_Y_DEST,
BG_X_DEST, BG_Y_DEST
};
static const GLfloat backgroundTexCoords[] = {
BG_X_ZERO, BG_Y_USEPERCENTAGE,
BG_X_USEPERCENTAGE, BG_Y_USEPERCENTAGE,
BG_X_ZERO, BG_Y_ZERO,
BG_X_USEPERCENTAGE, BG_Y_ZERO
};
// Turn on texturing
glEnable(GL_TEXTURE_2D);
// Clear to RED so that it's obvious when I'm not drawing my sprite on screen
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Texturing parameters - these make sense.. don't think they are the issue
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);//GL_LINEAR);
// Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, backgroundVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, 0, 0, backgroundTexCoords);
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, background->textureId);
// I don't understand what this uniform does in the texture2D call in shader.
glUniform1f(uniforms[UNIFORM_SAMPLERLOC], 0);
// Draw the geometry...
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// present the framebuffer see note [3]
[(EAGLView *)self.view presentFramebuffer];
注意[1] :
如果将BG_X_DEST设置为639.0f,则无法完全覆盖640像素,右侧显示红色。 但这对我来说没有意义-我的目标是像素完美,我必须将我的精灵几何图形从0绘制到640,而只有640时才是641像素! 红线以639f而不是640f出现
而且,如果我将BG_Y_DEST设置为959.0f,则不会显示红线。 红线顶部错误以958f而不是960或959f出现
这可能是我所遇到的错误的一个很好的线索。
注意:[2] -Xcode包含在OpenGL ES 2框架中
- (void)setFramebuffer
{
if (context)
{
[EAGLContext setCurrentContext:context];
if (!defaultFramebuffer)
[self createFramebuffer];
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
glViewport(0, 0, framebufferWidth, framebufferHeight);
}
}
注意事项[3]: -Xcode包含在OpenGL ES 2框架中
- (BOOL)presentFramebuffer
{
BOOL success = FALSE;
if (context)
{
[EAGLContext setCurrentContext:context];
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
success = [context presentRenderbuffer:GL_RENDERBUFFER];
}
return success;
}
注意[4] -相关的图像加载代码(我使用了带有和不带有Alpha通道的PNG,实际上似乎没有什么区别...我还尝试将代码更改为ARGB而不是RGBA,这就是错误-由于A = 1.0到处都是,所以我得到一个非常红色的图像,这使我认为RGBA实际上是有效的,并且此代码正确。): 更新:我已使用CG / ImageIO将纹理加载切换为完全不同的设置调用,并且看起来与此相同,因此我认为这不是图像库完成的某种混叠或颜色压缩(除非它们都进行相同的基本调用,这是可能的。)
// Otherwise it isn't already loaded
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);//GL_LINEAR);
// TODO Next 2 can prob go later on..
glGenTextures(1, &(newTexture->textureId)); // generate Texture
// Use this before 'drawing' the texture to the memory...
glBindTexture(GL_TEXTURE_2D, newTexture->textureId);
NSString *path = [[NSBundle mainBundle]
pathForResource:[NSString stringWithUTF8String:newTexture->filename.c_str()] ofType:@"png"];
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
UIImage *image = [[UIImage alloc] initWithData:texData];
if (image == nil)
NSLog(@"Do real error checking here");
newTexture->width = CGImageGetWidth(image.CGImage);
newTexture->height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc(newTexture->height * newTexture->width * 4 );
CGContextRef myContext = CGBitmapContextCreate
(imageData, newTexture->width, newTexture->height, 8, 4 * newTexture->width, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGColorSpaceRelease(colorSpace);
CGContextClearRect(myContext, CGRectMake(0, 0, newTexture->width, newTexture->height));
CGContextDrawImage(myContext, CGRectMake(0, 0, newTexture->width, newTexture->height), image.CGImage);
// Texture is created!
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, newTexture->width, newTexture->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CGContextRelease(myContext);
free(imageData);
[image release];
[texData release];
[(EAGLView *)self.view setContentScaleFactor:2.0f];
默认情况下,iPhone窗口会进行缩放以达到其高分辨率模式。 这在破坏我的图像质量..
谢谢大家的帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.