1
votes

I am in OpenGL es 2.0 with glKit trying to render to iOS devices.

Basically my goal is to instead of drawing to the main buffer draw to a texture. Then render that texture to the screen. I have been trying to follow another topic on so. Unfortunately they mention something about the power of two (im assuming with regards to resolution) but I don't know how to fix it. Anyway here is my swift interpretation of the code from that topic.

import Foundation
import GLKit
import OpenGLES

class RenderTexture {
    var framebuffer:GLuint = 0
    var tex:GLuint = 0
    var old_fbo:GLint = 0
    
    init(width: GLsizei, height: GLsizei)
    {
        glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &old_fbo)
        
        glGenFramebuffers(1, &framebuffer)
        glGenTextures(1, &tex)
        
        glBindFramebuffer(GLenum(GL_FRAMEBUFFER), framebuffer)
        glBindTexture(GLenum(GL_TEXTURE_2D), tex)
        glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGBA, GLsizei(width), GLsizei(height), 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), nil)
        glFramebufferTexture2D(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_TEXTURE_2D), tex, 0)
        
        glClearColor(0, 0.1, 0, 1)
        glClear(GLenum(GL_COLOR_BUFFER_BIT))
        
        let status = glCheckFramebufferStatus(GLenum(GL_FRAMEBUFFER))
        if (status != GLenum(GL_FRAMEBUFFER_COMPLETE))
        {
            print("DIDNT GO WELL WITH", width, " " , height)
            print(status)
        }
        
        glBindFramebuffer(GLenum(GL_FRAMEBUFFER), GLenum(old_fbo))
    }
    
    func begin()
    {
        glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &old_fbo)
        glBindFramebuffer(GLenum(GL_FRAMEBUFFER), framebuffer)
    }
    
    func end()
    {
        glBindFramebuffer(GLenum(GL_FRAMEBUFFER), GLenum(old_fbo))
    }
}

Then as far as rendering I have some things going on.

A code that theoretically renders any texture full screen. This has been tested with two manually loaded pngs (using no buffer changes) and works great.

func drawTriangle(texture: GLuint)
    {
        loadBuffers()
        //glViewport(0, 0, width, height)
        //glClearColor(0, 0.0, 0, 1.0)
        //glClear(GLbitfield(GL_COLOR_BUFFER_BIT) | GLbitfield(GL_DEPTH_BUFFER_BIT))
        
        
        glEnable(GLenum(GL_TEXTURE_2D))
        glActiveTexture(GLenum(GL_TEXTURE0))
        
        glUseProgram(texShader)
        let loc1 = glGetUniformLocation(texShader, "s_texture")
        glUniform1i(loc1, 0)
    
        
        let loc3 = glGetUniformLocation(texShader, "matrix")
        if (loc3 != -1)
        {
            glUniformMatrix4fv(loc3, 1, GLboolean(GL_FALSE), &matrix)
        }
        
        glBindTexture(GLenum(GL_TEXTURE_2D), texture)
        glDrawArrays(GLenum(GL_TRIANGLE_STRIP), 0, 6)
        glDisable(GLenum(GL_TEXTURE_2D))
        
        destroyBuffers()
    }

I also have a function that draws a couple dots on the screen. You dont really need to see the methods but it works. This is how I am going to know that OpenGL is drawing from the buffer texture and NOT a preloaded texture.

Finally here is the gist of the code I am trying to do.

func initialize()
{
      nfbo = RenderTexture(width: width, height: height)
}

fun draw()
{
        glViewport(0, 0, GLsizei(width * 2), GLsizei(height * 2)) //why do I have to multiply for 2 to get it to work????? 
        nfbo.begin()
        drawDots() //Draws the dots
        nfbo.end()
        reset()
        drawTriangle(nfbo.tex)
}

At the end of all this all that is drawn is a blank screen. If there is any more code that would help you figure things out let me know. I tried to trim it to make it less annoying for you.

Note: Considering the whole power of two thing I have tried passing the fbo class 512 x 512 just in case it would make things work being a power of two. Unfortunately it didnt do that.

Another Note: All I am doing is going to be 2D so I dont need depth buffers right?

1
Why not just debug it by taking the read pixels, also check if any gl error. - Ta-Zvi
@Ta-Zvi what functions check for gl errors? And how do I interpret then. - J.Doe
Also i cant get the glReadPixels function to work - J.Doe
Make sure that you set the right texture parameters with glTexParameteri(). The defaults will not work in many use cases, including the code posted here. Any OpenGL tutorial will explain how they need to be set. - Reto Koradi
@RetroKoradi your right! That was the problem. After you telling me that I decided I should try overwriting a texture unit I knew was working one made by glkit. And it works now! I wish their were a better way then this but at least it works! - J.Doe

1 Answers

3
votes

yesterday I saw exactly the same issue.

after struggling for hours, I found out why.

the trick is configuring your texture map with the following:

    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GL_CLAMP_TO_EDGE);
    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GL_CLAMP_TO_EDGE);

otherwise, you won't draw anything on the texture map.

the reason seems to be that while ios supports texture maps that are not power of 2. it requires GL_CLAMP_TO_EDGE. otherwise it won't work.

it should really report incomplete framebuffer. it took me quite long time to debug this problem!

here a related discussion:

Rendering to non-power-of-two texture on iPhone