Results 1 to 3 of 3

Thread: Blending multiple textures on a quad [OpenGL ES 2 iOS 5.1]

  1. #1
    Junior Member
    Join Date
    Jun 2012
    Posts
    2

    Blending multiple textures on a quad [OpenGL ES 2 iOS 5.1]

    Hi,

    I'm just getting started with OpenGL ES 2.0, and trying to blend a series of 5 or 6 layers onto a quad. I am attempting to load each texture into a texture slot, and combine them in a fragment shader. Unfortunately, only the texture loaded into GL_TEXTURE0 is appearing (even if I try to display another slot's texture independently).

    I'm not sure if I am loading the other textures correctly. Could somebody take a quick look at my code (especially the render method and fragment shader), and let me know where I'm going wrong?

    Many thanks

    Code :
    //
    //  OpenGLView.h
    //
     
    #import <UIKit/UIKit.h>
    #import <QuartzCore/QuartzCore.h>
    #include <OpenGLES/ES2/gl.h>
    #include <OpenGLES/ES2/glext.h>
     
    @interface OpenGLView : UIView {
     
        CAEAGLLayer* _eaglLayer;
        EAGLContext* _context;
     
        GLuint _colorRenderBuffer;
        GLuint _vertexBuffer;
        GLuint _indexBuffer;
     
        GLuint _positionSlot;
        GLuint _colorSlot;
        GLuint _texCoordSlot; 
     
        GLuint _bgTexture;
        GLuint _layer1Texture;
        GLuint _layer2Texture;
        GLuint _layer3Texture;
        GLuint _layer4Texture;
        GLuint _layer5Texture;
     
        GLuint _textureBackground;
        GLuint _textureLayer1;    
        GLuint _textureLayer2;
        GLuint _textureLayer3;
        GLuint _textureLayer4;
        GLuint _textureLayer5;
     
    }
     
    @end

    Code :
    //
    //  OpenGLView.m
     
    #import "OpenGLView.h"
     
    @implementation OpenGLView
     
    typedef struct {
        float Position[3];
        float Color[4];
        float TexCoord[2];
    } Vertex;
     
    #define TEX_COORD_MAX 1
     
    const Vertex Vertices[] = {
        // Front
        {{1, -1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}},
        {{1, 1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}},
        {{-1, 1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}},
        {{-1, -1, 0}, {0, 0, 0, 1}, {0, 0}},
     
    };
     
    const GLubyte Indices[] = {
        // Front
        0, 1, 2,
        2, 3, 0
    };
     
     
    + (Class)layerClass {
        return [CAEAGLLayer class];
    }
     
    - (void)setupLayer {
        _eaglLayer = (CAEAGLLayer*) self.layer;
        _eaglLayer.opaque = YES;
    }
     
    - (void)setupContext {   
        EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2;
        _context = [[EAGLContext alloc] initWithAPI:api];
        if (!_context) {
            NSLog(@"Failed to initialize OpenGLES 2.0 context");
            exit(1);
        }
     
        if (![EAGLContext setCurrentContext:_context]) {
            NSLog(@"Failed to set current OpenGL context");
            exit(1);
        }
    }
     
    - (void)setupRenderBuffer {
        glGenRenderbuffers(1, &_colorRenderBuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);        
        [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];    
    }
     
    - (void)setupFrameBuffer {    
        GLuint framebuffer;
        glGenFramebuffers(1, &framebuffer);
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);   
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
    }
     
    - (GLuint)compileShader:(NSString*)shaderName withType:(GLenum)shaderType {
     
        NSString* shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:@"glsl"];
        NSError* error;
        NSString* shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
        if (!shaderString) {
            NSLog(@"Error loading shader: %@", error.localizedDescription);
            exit(1);
        }
     
        GLuint shaderHandle = glCreateShader(shaderType);    
     
        const char * shaderStringUTF8 = [shaderString UTF8String];    
        int shaderStringLength = [shaderString length];
        glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);
     
        glCompileShader(shaderHandle);
     
        GLint compileSuccess;
        glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
        if (compileSuccess == GL_FALSE) {
            GLchar messages[256];
            glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
            NSString *messageString = [NSString stringWithUTF8String:messages];
            NSLog(@"%@", messageString);
            exit(1);
        }
     
        return shaderHandle;
     
    }
     
    - (void)compileShaders {
     
        GLuint vertexShader = [self compileShader:@"SimpleVertex" withType:GL_VERTEX_SHADER];
        GLuint fragmentShader = [self compileShader:@"SimpleFragment" withType:GL_FRAGMENT_SHADER];
     
        GLuint programHandle = glCreateProgram();
        glAttachShader(programHandle, vertexShader);
        glAttachShader(programHandle, fragmentShader);
        glLinkProgram(programHandle);
     
        GLint linkSuccess;
        glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
        if (linkSuccess == GL_FALSE) {
            GLchar messages[256];
            glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
            NSString *messageString = [NSString stringWithUTF8String:messages];
            NSLog(@"%@", messageString);
            exit(1);
        }
     
        glUseProgram(programHandle);
     
        _positionSlot = glGetAttribLocation(programHandle, "Position");
        _colorSlot = glGetAttribLocation(programHandle, "SourceColor");
        glEnableVertexAttribArray(_positionSlot);
        glEnableVertexAttribArray(_colorSlot);
     
        _texCoordSlot = glGetAttribLocation(programHandle, "TexCoordIn");
        glEnableVertexAttribArray(_texCoordSlot);
     
        _textureBackground = glGetUniformLocation(programHandle, "TextureBackground");
        _textureLayer1 = glGetUniformLocation(programHandle, "TextureLayer1");
        _textureLayer2 = glGetUniformLocation(programHandle, "TextureLayer2");  
        _textureLayer3 = glGetUniformLocation(programHandle, "TextureLayer3");  
        _textureLayer4 = glGetUniformLocation(programHandle, "TextureLayer4");  
        _textureLayer5 = glGetUniformLocation(programHandle, "TextureLayer5");  
    }
     
    - (void)setupVBOs {
     
        glGenBuffers(1, &_vertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
     
        glGenBuffers(1, &_indexBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
     
     
    }
     
    - (void)render:(CADisplayLink*)displayLink {
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
        glDisable(GL_DEPTH_TEST);
     
        glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
     
        glViewport(0, 0, self.frame.size.width, self.frame.size.height);
     
        glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
     
        glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
        glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
     
        glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));    
     
        glActiveTexture(GL_TEXTURE0); 
        glBindTexture(GL_TEXTURE_2D, _bgTexture);
        glUniform1i(_textureBackground, 0); 
     
        glActiveTexture(GL_TEXTURE1); 
        glBindTexture(GL_TEXTURE_2D, _layer1Texture);
        glUniform1i(_textureLayer1, 0);  
     
        glActiveTexture(GL_TEXTURE2); 
        glBindTexture(GL_TEXTURE_2D, _layer2Texture);
        glUniform1i(_textureLayer2, 0); 
     
        glActiveTexture(GL_TEXTURE3); 
        glBindTexture(GL_TEXTURE_2D, _layer3Texture);
        glUniform1i(_textureLayer3, 0); 
     
        glActiveTexture(GL_TEXTURE4); 
        glBindTexture(GL_TEXTURE_2D, _layer4Texture);
        glUniform1i(_textureLayer4, 0); 
     
        glActiveTexture(GL_TEXTURE5); 
        glBindTexture(GL_TEXTURE_2D, _layer5Texture);
        glUniform1i(_textureLayer5, 0); 
     
        glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);
     
        [_context presentRenderbuffer:GL_RENDERBUFFER];
    }
     
     
    - (void)setupDisplayLink {
        CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render:)];
        [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];    
    }
     
     
    - (GLuint)setupTexture:(NSString *)fileName {
     
        CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
        if (!spriteImage) {
            NSLog(@"Failed to load image %@", fileName);
            exit(1);
        }
     
        size_t width = CGImageGetWidth(spriteImage);
        size_t height = CGImageGetHeight(spriteImage);
     
        GLubyte * spriteData = (GLubyte *) calloc(width*height*4, sizeof(GLubyte));
     
        CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);    
     
        CGContextTranslateCTM (spriteContext, 0, height);
        CGContextScaleCTM (spriteContext
                           , 1.0, -1.0);    
     
        CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
     
        CGContextRelease(spriteContext);
     
        GLuint texName;
        glGenTextures(1, &texName);
        glBindTexture(GL_TEXTURE_2D, texName);
     
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
     
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
     
        free(spriteData);        
        return texName;
     
    }
     
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {        
            [self setupLayer];        
            [self setupContext];    
            [self setupRenderBuffer];        
            [self setupFrameBuffer];     
            [self compileShaders];
            [self setupVBOs];
            [self setupDisplayLink];
            _bgTexture = [self setupTexture:@"background.tif"];
            _layer1Texture = [self setupTexture:@"layer1.tif"];
            _layer2Texture = [self setupTexture:@"layer2.tif"];
            _layer3Texture = [self setupTexture:@"layer3.tif"];
            _layer4Texture = [self setupTexture:@"layer4.tif"];
            _layer5Texture = [self setupTexture:@"layer5.tif"];
        }
        return self;
    }
     
    @end

    Code :
    // SimpleVertex.glsl
     
    attribute vec4 Position;
    attribute vec4 SourceColor; 
     
    varying vec4 DestinationColor; 
     
    attribute vec2 TexCoordIn;
    varying vec2 TexCoordOut;
     
    void main(void) {
        DestinationColor = SourceColor; 
        gl_Position = Position;
        TexCoordOut = TexCoordIn;
    }


    Code :
    // SimpleFragment.glsl
     
    varying lowp vec2 TexCoordOut;
    varying lowp vec4 DestinationColor;
     
    uniform sampler2D TextureBackground;
    uniform sampler2D TextureLayer1;
    uniform sampler2D TextureLayer2;
    uniform sampler2D TextureLayer3;
    uniform sampler2D TextureLayer4;
    uniform sampler2D TextureLayer5;
     
    void main(void) {
        gl_FragColor = DestinationColor *  texture2D(TextureLayer1, TexCoordOut);
        // if i replace TextureLayer1 with TextureBackground, it will display that image as it is in GLTEXTURE_0
    }

  2. #2
    Junior Member
    Join Date
    Jun 2012
    Posts
    2

    Re: Blending multiple textures on a quad [OpenGL ES 2 iOS 5.

    This has now been solved, the errors were in the calls to glUniform1i(_textureLayern, 0), which should have reflected the correct texture unit in the second argument.

  3. #3
    Junior Member
    Join Date
    Jun 2012
    Posts
    19

    Re: Blending multiple textures on a quad [OpenGL ES 2 iOS 5.

    hey left blank. i am rendering two textures on the screen. i am able to see both textures.

    I want to run translation/ rotation on the top layer. but when i do it appears on both the layers. can you tell me how to create a translation or rotation on top texture and keep the lower texture unmoved.




    I have similar code like u with a update function which updates the rotation of the texture. i am not knowing how to do it on single texture(top one)

    Thank you.

Similar Threads

  1. rendering multiple OpenGL views within a single UIView (iOS)
    By cedoucette in forum OpenGL ES 1.X - fixed function hardware
    Replies: 1
    Last Post: 05-09-2011, 07:21 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •