OpenGL ES 如何正确组合 Orthof 和 Frustum

发布于 2025-01-02 11:04:26 字数 6415 浏览 4 评论 0原文

我开始学习 iPhone 的 OpenGL ES 1.1,并且想在一些 3D 对象后面以正交投影绘制 2D 图像。使用 Jeff Lamarche 的教程和《Pro OpenGL ES for iPhone》一书,我想出了以下几种方法来尝试做到这一点。如果我禁用对 drawSunInRect 的调用,则 3D 对象渲染得很好,我可以使用触摸控件等移动它们。如果我取消注释该调用并尝试绘制太阳图像,该图像将出现在 < code>CGRect 我提供,但我看不到任何其他 3D 对象 - 屏幕的其余部分是黑色的。我尝试在各个地方禁用/启用深度测试,将不同的参数传递给 glOrthof(),并围绕矩形移动,但只有在 drawSunInRect 时我才不断获取太阳图像code> 方法被调用。我假设它覆盖了我的 3D 对象。

// Draw Sun in Rect and with Depth
- (void)drawSunInRect:(CGRect)rect withDepth:(float)depth {

    // Get screen bounds
    CGRect frame = [[UIScreen mainScreen] bounds];

    // Calculate vertices from passed CGRect and depth
    GLfloat  vertices[] = 
    {
        rect.origin.x, rect.origin.y, depth,

        rect.origin.x + rect.size.width , rect.origin.y, depth,

        rect.origin.x, rect.size.height+rect.origin.y , depth,

        rect.origin.x + rect.size.width , rect.size.height+rect.origin.y ,depth
    };

    // Map the texture coords - no repeating
    static  GLfloat textureCoords[] = 
    {               
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        1.0, 1.0
    };

    // Disable DEPTH test and setup Ortho
    glDisable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrthof(0,frame.size.width,frame.size.height,0,0.1f,1000.0); 

    // Enable blending and configure
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

    // Enable VERTEX and TEXTURE client states
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    // Enable Textures
    glEnable(GL_TEXTURE_2D); 

    // Projection Matrix Mode for ortho and reset
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();     
    glLoadIdentity();      

    // No lighting or Depth Mask for 2D - no Culling
    glDisable(GL_LIGHTING);                                                                                          
    glDepthMask(GL_FALSE);
    glDisable(GL_CULL_FACE);
    glDisableClientState(GL_COLOR_ARRAY);   

    // Define ortho
    glOrthof(0,frame.size.width,frame.size.height,0,0.1f,1000); 

     // From Jeff Lamarche Tutorials
     // glOrthof(-1.0,                                          // Left
     // 1.0,                                                    // Right
     // -1.0 / (rect.size.width / rect.size.height),            // Bottom
     // 1.0 / (rect.size.width / rect.size.height),             // Top
     // 0.01,                                                   // Near
     // 10000.0);                                               // Far

    // Setup Model View Matrix
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    // Bind and draw the Texture
    glBindTexture(GL_TEXTURE_2D,sunInt);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glTexCoordPointer(2, GL_FLOAT,0,textureCoords);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glMatrixMode(GL_MODELVIEW); 
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    // Re-enable lighting 
    glEnable(GL_LIGHTING);  
    glDisable(GL_TEXTURE_2D);   
    glDisable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDepthMask(GL_TRUE);

}


// Override the draw in rect function
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{

    // Initialize and init the rotation stuff for the object
    // Identity Matrix
    glLoadIdentity();
    static GLfloat rot = 0.0;

    // Clear any remnants in the drawing buffers
    // and fill the background with black
    glClearColor(0.0f,0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Render the Sun - 2D Sun Image in CGRect
    //[self drawSunInRect:CGRectMake(100, 100, 50, 50) withDepth:-30.0]; // 2D Sun Image

    // Render the BattleCruiser - 3D Battlecruiser
    [self renderTheBattleCruiser];

    // Calculate a time interval to use to rotate the cruiser lives
    static NSTimeInterval lastDrawTime;
    if (lastDrawTime)
    {
        NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;
        rot += 75 * timeSinceLastDraw;                
    }
    lastDrawTime = [NSDate timeIntervalSinceReferenceDate];

}

更新

我修改了绘制太阳方法,使 GL_PROJECTION 仅有 1 次推送和 1 次弹出。我仍然有同样的问题。太阳图像出现,但我看不到 3D 对象。我尝试重新安排对渲染方法的调用,以便首先渲染 3D 对象,但我得到了相同的结果。我很欣赏有关如何同时查看正交纹理和 3D 对象的其他想法。

// Draw Sun in Rect and with Depth
- (void)drawSunInRect:(CGRect)rect withDepth:(float)depth {

    // Get screen bounds
    CGRect frame = [[UIScreen mainScreen] bounds];

    // Calculate vertices from passed CGRect and depth
    GLfloat  vertices[] = 
    {
        rect.origin.x, rect.origin.y, depth,

        rect.origin.x + rect.size.width , rect.origin.y, depth,

        rect.origin.x, rect.size.height+rect.origin.y , depth,

        rect.origin.x + rect.size.width , rect.size.height+rect.origin.y ,depth
    };

    // Map the texture coords - no repeating
    static  GLfloat textureCoords[] = 
    {               
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        1.0, 1.0
    };

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_TEXTURE_2D); 

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();     
    glLoadIdentity();      

    glDisable(GL_LIGHTING);                                                                                          
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);
    glDisableClientState(GL_COLOR_ARRAY);   

    glOrthof(0,frame.size.width,frame.size.height,0,0,1000);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    glColor4f(1,1,1,1);

    glBindTexture(GL_TEXTURE_2D,sunInt);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glTexCoordPointer(2, GL_FLOAT,0,textureCoords);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glMatrixMode(GL_MODELVIEW); 
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glEnable(GL_LIGHTING);  
    glDisable(GL_TEXTURE_2D);   
    glDisable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

I am beginning to learn OpenGL ES 1.1 for iPhone and would like to draw a 2D image in orthographic projection behind a few 3D objects. Using Jeff Lamarche's tutorials and the book Pro OpenGL ES for iPhone and I've come up with the following couple methods to attempt to do this. If I disable the call to drawSunInRect the 3D objects are rendered just fine and I can move them with touch controls etc. If I uncomment that call and try to draw the sun image, the image appears in the CGRect I supply, but I cannot see any of my other 3D objects - the rest of the screen is black. I've tried to disable/enable depth testing in various places, pass different parameters to glOrthof(), and move around the rectangle but I keep getting the sun image only when the drawSunInRect method is called. I'm assuming it is covering my 3D objects.

// Draw Sun in Rect and with Depth
- (void)drawSunInRect:(CGRect)rect withDepth:(float)depth {

    // Get screen bounds
    CGRect frame = [[UIScreen mainScreen] bounds];

    // Calculate vertices from passed CGRect and depth
    GLfloat  vertices[] = 
    {
        rect.origin.x, rect.origin.y, depth,

        rect.origin.x + rect.size.width , rect.origin.y, depth,

        rect.origin.x, rect.size.height+rect.origin.y , depth,

        rect.origin.x + rect.size.width , rect.size.height+rect.origin.y ,depth
    };

    // Map the texture coords - no repeating
    static  GLfloat textureCoords[] = 
    {               
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        1.0, 1.0
    };

    // Disable DEPTH test and setup Ortho
    glDisable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrthof(0,frame.size.width,frame.size.height,0,0.1f,1000.0); 

    // Enable blending and configure
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

    // Enable VERTEX and TEXTURE client states
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    // Enable Textures
    glEnable(GL_TEXTURE_2D); 

    // Projection Matrix Mode for ortho and reset
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();     
    glLoadIdentity();      

    // No lighting or Depth Mask for 2D - no Culling
    glDisable(GL_LIGHTING);                                                                                          
    glDepthMask(GL_FALSE);
    glDisable(GL_CULL_FACE);
    glDisableClientState(GL_COLOR_ARRAY);   

    // Define ortho
    glOrthof(0,frame.size.width,frame.size.height,0,0.1f,1000); 

     // From Jeff Lamarche Tutorials
     // glOrthof(-1.0,                                          // Left
     // 1.0,                                                    // Right
     // -1.0 / (rect.size.width / rect.size.height),            // Bottom
     // 1.0 / (rect.size.width / rect.size.height),             // Top
     // 0.01,                                                   // Near
     // 10000.0);                                               // Far

    // Setup Model View Matrix
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    // Bind and draw the Texture
    glBindTexture(GL_TEXTURE_2D,sunInt);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glTexCoordPointer(2, GL_FLOAT,0,textureCoords);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glMatrixMode(GL_MODELVIEW); 
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    // Re-enable lighting 
    glEnable(GL_LIGHTING);  
    glDisable(GL_TEXTURE_2D);   
    glDisable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDepthMask(GL_TRUE);

}


// Override the draw in rect function
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{

    // Initialize and init the rotation stuff for the object
    // Identity Matrix
    glLoadIdentity();
    static GLfloat rot = 0.0;

    // Clear any remnants in the drawing buffers
    // and fill the background with black
    glClearColor(0.0f,0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Render the Sun - 2D Sun Image in CGRect
    //[self drawSunInRect:CGRectMake(100, 100, 50, 50) withDepth:-30.0]; // 2D Sun Image

    // Render the BattleCruiser - 3D Battlecruiser
    [self renderTheBattleCruiser];

    // Calculate a time interval to use to rotate the cruiser lives
    static NSTimeInterval lastDrawTime;
    if (lastDrawTime)
    {
        NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;
        rot += 75 * timeSinceLastDraw;                
    }
    lastDrawTime = [NSDate timeIntervalSinceReferenceDate];

}

UPDATE

I modified the draw sun method to have only 1 push and 1 pop for the GL_PROJECTION. I am still having the same issue. The sun image appears but I cannot see my 3D Objects. I have tried to re-arrange the calls to the render methods so the 3D objects are rendered first but I get the same results. I would appreciate other ideas on how to see my orthographic texture and 3D objects together.

// Draw Sun in Rect and with Depth
- (void)drawSunInRect:(CGRect)rect withDepth:(float)depth {

    // Get screen bounds
    CGRect frame = [[UIScreen mainScreen] bounds];

    // Calculate vertices from passed CGRect and depth
    GLfloat  vertices[] = 
    {
        rect.origin.x, rect.origin.y, depth,

        rect.origin.x + rect.size.width , rect.origin.y, depth,

        rect.origin.x, rect.size.height+rect.origin.y , depth,

        rect.origin.x + rect.size.width , rect.size.height+rect.origin.y ,depth
    };

    // Map the texture coords - no repeating
    static  GLfloat textureCoords[] = 
    {               
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        1.0, 1.0
    };

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_TEXTURE_2D); 

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();     
    glLoadIdentity();      

    glDisable(GL_LIGHTING);                                                                                          
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);
    glDisableClientState(GL_COLOR_ARRAY);   

    glOrthof(0,frame.size.width,frame.size.height,0,0,1000);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    glColor4f(1,1,1,1);

    glBindTexture(GL_TEXTURE_2D,sunInt);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glTexCoordPointer(2, GL_FLOAT,0,textureCoords);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glMatrixMode(GL_MODELVIEW); 
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glEnable(GL_LIGHTING);  
    glDisable(GL_TEXTURE_2D);   
    glDisable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

末が日狂欢 2025-01-09 11:04:27

我意识到我在 viewController viewDidLoad 中只调用了一次 setClipping 。我将它移动到我的 glkView 方法中,现在我得到了我的太阳图像和我的 3d 对象。

I realized I was calling setClipping only once in my viewController viewDidLoad. I moved it to my glkView method and now I get my Sun image and my 3d object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文