纹理上的片段着色器
Posted
技术标签:
【中文标题】纹理上的片段着色器【英文标题】:Fragment shaders on a texture 【发布时间】:2010-03-14 15:21:54 【问题描述】:我正在尝试为程序添加一些后处理功能。渲染是使用openGL完成的。我只是想让程序加载一些自制的片段着色器并在视频流上使用它们。
我使用“OpenGL Shader Builder”编写了一小段着色器,它只是将纹理转换为灰度。着色器在着色器构建器中运行良好,但我无法使其在主程序中运行。屏幕保持全黑。
这里是设置:
@implementation PluginGLView
- (id) initWithCoder: (NSCoder *) coder
const GLubyte * strExt;
if ((self = [super initWithCoder:coder]) == nil)
return nil;
glLock = [[NSLock alloc] init];
if (nil == glLock)
[self release];
return nil;
// Init pixel format attribs
NSOpenGLPixelFormatAttribute attrs[] =
NSOpenGLPFAAccelerated,
NSOpenGLPFANoRecovery,
NSOpenGLPFADoubleBuffer,
0
;
// Get pixel format from OpenGL
NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
if (!pixFmt)
NSLog(@"No Accelerated OpenGL pixel format found\n");
NSOpenGLPixelFormatAttribute attrs2[] =
NSOpenGLPFANoRecovery,
0
;
// Get pixel format from OpenGL
pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs2];
if (!pixFmt)
NSLog(@"No OpenGL pixel format found!\n");
[self release];
return nil;
[self setPixelFormat:[pixFmt autorelease]];
/*
long swapInterval = 1 ;
[[self openGLContext]
setValues:&swapInterval
forParameter:NSOpenGLCPSwapInterval];
*/
[glLock lock];
[[self openGLContext] makeCurrentContext];
// Init object members
strExt = glGetString (GL_EXTENSIONS);
texture_range = gluCheckExtension ((const unsigned char *)"GL_APPLE_texture_range", strExt) ? GL_TRUE : GL_FALSE;
texture_hint = GL_STORAGE_SHARED_APPLE ;
client_storage = gluCheckExtension ((const unsigned char *)"GL_APPLE_client_storage", strExt) ? GL_TRUE : GL_FALSE;
rect_texture = gluCheckExtension((const unsigned char *)"GL_EXT_texture_rectangle", strExt) ? GL_TRUE : GL_FALSE;
// Setup some basic OpenGL stuff
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Loads the shaders
shader=LoadShader(GL_FRAGMENT_SHADER,"/Users/alexandremathieu/fragment.fs");
program=glCreateProgram();
glAttachShader(program, shader);
glLinkProgram(program);
glUseProgram(program);
[NSOpenGLContext clearCurrentContext];
[glLock unlock];
image_width = 1024;
image_height = 512;
image_depth = 16;
image_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
image_base = (GLubyte *) calloc(((IMAGE_COUNT * image_width * image_height) / 3) * 4, image_depth >> 3);
if (image_base == nil)
[self release];
return nil;
// Create and load textures for the first time
[self loadTextures:GL_TRUE];
// Init fps timer
//gettimeofday(&cycle_time, NULL);
drawBG = YES;
// Call for a redisplay
noDisplay = YES;
PSXDisplay.Disabled = 1;
[self setNeedsDisplay:true];
return self;
这里是“渲染屏幕”功能,它基本上...渲染屏幕。
- (void)renderScreen
int bufferIndex = whichImage;
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, bufferIndex+1);
glUseProgram(program);
int loc=glGetUniformLocation(program, "texture");
glUniform1i(loc,bufferIndex+1);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, image_width, image_height, GL_BGRA, image_type, image[bufferIndex]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f, 1.0f);
glTexCoord2f(0.0f, image_height);
glVertex2f(-1.0f, -1.0f);
glTexCoord2f(image_width, image_height);
glVertex2f(1.0f, -1.0f);
glTexCoord2f(image_width, 0.0f);
glVertex2f(1.0f, 1.0f);
glEnd();
[[self openGLContext] flushBuffer];
[NSOpenGLContext clearCurrentContext];
//[glLock unlock];
最后是着色器。
uniform sampler2DRect texture;
void main()
vec4 color, texel;
color = gl_Color;
texel = texture2DRect(texture, gl_TexCoord[0].xy);
color *= texel;
// Begin Shader
float gray=0.0;
gray+=(color.r + color.g + color.b)/3.0;
color=vec4(gray,gray,gray,color.a);
// End Shader
gl_FragColor = color;
着色器的加载和使用工作正常,因为我可以使用此着色器将屏幕全部变为红色
void main()
gl_FragColor=vec4(1.0,0.0,0.0,1.0);
如果着色器包含语法错误,我会收到来自 LoadShader 函数等的错误消息。如果我删除着色器的使用,一切都会正常工作。
我认为问题来自“将纹理作为统一参数传递”的事情。但这是我使用 openGL 的第一步,我不能确定任何事情。
【问题讨论】:
我会研究 Luminance 以生成好的灰度图像:en.wikipedia.org/wiki/Luma_%28video%29 【参考方案1】:纹理采样器必须设置为活动纹理单元的数量。因此,例如使用 glActiveTexture(GL_TEXTURE3) 采样器也必须设置为 3。在你的情况下,数字应该是 0。
【讨论】:
以上是关于纹理上的片段着色器的主要内容,如果未能解决你的问题,请参考以下文章