Question

Je suis en train d'ajouter des capacités de post-traitement à un programme. Le rendu est fait en utilisant openGL. Je veux juste permettre au programme de charger une maison en fragment shader et de les utiliser sur le flux vidéo.

J'ai écrit un petit morceau de shaders en utilisant « OpenGL Shader Builder » qui tourne juste une texture en niveaux de gris. Les shaders fonctionne bien dans le générateur de shaders, mais je ne peux pas le faire fonctionner dans le programme principal. Les écrans reste tout noir.

Voici la configuration:

@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;
}

Et est ici la fonction "écran render" Wich essentiellement ... rend l'écran.

- (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];

}

et enfin est le shader ici.

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;
 }

Le chargement et l'utilisation des shaders fonctionne depuis que je suis capable de tourner l'écran tout rouge avec ce shader

void main(){
    gl_FragColor=vec4(1.0,0.0,0.0,1.0);
}

Si le shader contient une erreur de syntaxe, je reçois un message d'erreur de la fonction LoadShader etc. Si je supprime l'utilisation du shader, tout fonctionne normalement.

Je pense que le problème vient du « passage de la texture comme paramètre uniforme » chose. Mais ce sont mes premières très étape avec openGL et je ne peux pas être sûr de quoi que ce soit.

Ne pas hésiter à demander plus d'informations.

Merci Stack O.

Était-ce utile?

La solution

échantillonneurs de texture doivent être mis au nombre de l'unité de texture active. Ainsi, par exemple avec glActiveTexture (GL_TEXTURE3) l'échantillonneur doit être réglé sur 3 ainsi. Dans votre cas, le nombre doit être 0.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top