iOS - Comment dessiner une YUV image à l'aide d'openGL
Actuellement, je suis en train d'essayer de dessiner une image en utilisant openGL (l'image est mise à jour très souvent, et donc doit être redessiné). Auparavant, j'ai été la conversion de mon image de YUV RVB, puis à l'aide de cette nouvelle image pour dessiner avec openGL. Tout a bien fonctionné, mais le processus de conversion n'a pas été particulièrement rapide.
Je suis en train d'essayer de modifier le code afin que la conversion est pris en charge dans les shaders openGL. Après avoir regardé autour, j'ai trouvé un couple de fragments de code (en particulier les shaders et la majeure partie de mes renderImage fonction) qui m'ont aidé à obtenir une ligne de base, mais je n'arrive pas à réellement obtenir l'image pour dessiner correctement tout ce que je vois est une image noire.
Il est très probable que je suis absent quelque chose d'extrêmement simple et important - Mon expérience avec openGL est plutôt limitée. Si quelqu'un peut jeter un oeil et voir si ils reconnaissent quelque chose de mal, s'il vous plaît laissez-moi savoir.
Je précise, je suis en train de soutien iOS 4.x, de sorte CVOpenGLESTextureCacheCreateTexturefromimage ne devrait pas être utilisable (et je ne suis pas vraiment positif comment le programme d'installation de l'utiliser même si je le voulais).
Toute aide serait appréciée. Le Code ci-dessous -
Mon Vertex shader:
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;
void main()
{
gl_Position = position;
textureCoordinate = inputTextureCoordinate.xy;
}
Fragment Shader:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 textureCoordinate;
uniform sampler2D videoFrame;
uniform sampler2D videoFrameUV;
const mat3 yuv2rgb = mat3(
1, 0, 1.2802,
1, -0.214821, -0.380589,
1, 2.127982, 0
);
void main() {
vec3 yuv = vec3(
1.1643 * (texture2D(videoFrame, textureCoordinate).r - 0.0625),
texture2D(videoFrameUV, textureCoordinate).r - 0.5,
texture2D(videoFrameUV, textureCoordinate).a - 0.5
);
vec3 rgb = yuv * yuv2rgb;
gl_FragColor = vec4(rgb, 1.0);
}
La renderImage fonction:
-(void)renderImage:(ImageBuffer *)image
{
if (image)
{
int bufferHeight = image->GetHeight();
int bufferWidth = image->GetWidth();
if(!imageTexture){
//Dealing with the Y portion of the YCbCr
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &imageTexture);
//Bind Y texture
glBindTexture(GL_TEXTURE_2D, imageTexture);
glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
//For fitting
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//This is necessary for non-power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, bufferWidth, bufferHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, image->GetPlanePointer(0));
//Dealing with the CbCr potion of the YCbCr
glActiveTexture(GL_TEXTURE1);
glGenTextures(1, &imageTextureUV);
//Bind CbCr texture
glBindTexture(GL_TEXTURE_2D, imageTextureUV);
glUniform1i(uniforms[UNIFORM_VIDEOFRAMEUV], 1);
//For fitting
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//This is necessary for non-power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, bufferWidth/2, bufferHeight/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, image->GetPlanePointer(1));
}
[self drawFrame];
}
}
Et enfin, l'étirage de la fonction:
- (void)drawFrame
{
[self setFramebuffer];
//Replace the implementation of this method to do your own custom drawing.
static const GLfloat squareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
static const GLfloat textureVertices[] = {
// 1.0f, 1.0f,
// 1.0f, 0.0f,
// 0.0f, 1.0f,
// 0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
// 0.0f, 0.8f,
// 1.0f, 0.8f,
// 0.0f, 0.2f,
// 1.0f, 0.2f
};
static float transY = 0.0f;
if ([context API] == kEAGLRenderingAPIOpenGLES2) {
//Use shader program.
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, imageTexture);
//Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, imageTextureUV);
//Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
//Validate program before drawing. This is a good check, but only really necessary in a debug build.
//DEBUG macro must be defined in your debug configurations if that's not already the case.
#if defined(DEBUG)
if (![self validateProgram:program]) {
NSLog(@"Failed to validate program: %d", program);
return;
}
#endif
} else {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
transY += 0.075f;
glVertexPointer(2, GL_FLOAT, 0, squareVertices);
glEnableClientState(GL_VERTEX_ARRAY);
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[self presentFramebuffer];
}
glUseProgram(program);
avant votre glUniform1i()
appels assurez-vous que le programme est actif et que vous êtes à la définition de la texture uniformes sur le correctement. Aussi, assurez-vous que vous avez défini le contexte actuel avant de le faire. Ce sont deux choses qui ont déclenché moi dans le passé.ouais, je ne les différentes configuration de base dans une fonction distincte appelé plus tôt - le contexte, la compilation des shaders, et de lier le programme devrait être fait avant renderImage() est appelée. J'ai déplacé un glUseProgram() appel avant que le glUniform1i() appelle, mais ne semble pas changer quoi que ce soit malheureusement.
Pardon pour mon ignorance de ce qui est exposé dans iOS OpenGL ES, mais le GPU PowerVR matériel peut décoder certains YUV textures (au moins selon pandorawiki.org/...). Il n'y a pas d'OpenGL ES extension?
OriginalL'auteur Doc | 2012-09-14
Vous devez vous connecter pour publier un commentaire.
Voici quelques extraits de code à partir de mon projet " movie player pour iOS.
1. fragment shader
2. créer des textures à partir de YUV420p cadre
3. init sommets et la texture coords
4. cadre de rendu de
La lien vers le projet sur github.
OriginalL'auteur Kolyvan