Jump to content

  • Log In with Google      Sign In   
  • Create Account

haegarr

Member Since 10 Oct 2005
Offline Last Active Today, 11:13 AM

Topics I've Started

How to write a custom CAValueFunction (iOS)?

15 January 2011 - 11:31 AM

New year, new question ;)

Speaking of iOS: I'm in the necessity to write a custom CAValueFunction (that computes a CATransform3D from an angle). The pre-defined functions are not sufficient, because I need to compute a product like
M1 * M2 * M3
where just M2 is animated (by a kCAValueFunctionRotateY). A custom CAValueFunction would solve the problem smartly. However, it seems me from Apple's documentation, that writing a custom CAValueFunction is not wanted (by Apple, not by me ;)), because I can't find the description (of the API) how a value function works in detail. Has anybody here already done such a thing, please?

FBO, BlitFramebuffer / CopyPixels and GL_FRONT

11 April 2010 - 10:18 PM

Hi. Yesterday I hit a poblem during programming an intro animation: The purpose is to make a screenshot of the desktop a.t.m. of starting the game, and to play a little 3D animation with the desktop image in the background. The technique I've intended to use is as follows: (1) making a double buffered full-screen context (works fine) (2) making an FBO with a solely render buffer attachment, matching the display (works fine) (3) copying the front buffer to the FBO's color attachment 0 (doesn't work) (4) copying the FBO's color attachment 0 to the back buffer (works fine) (5) rendering the animation into the back buffer (works fine) (6) swapping back to front (works fine) (7) loop back to (4) With my possibilities, I can use glBlitFramebufferEXT (on Mac OS X 10.5.8 w/ ATI X1900XT) or glCopyPixels (same as before, and also on Mac OS X 10.5.2 w/ NVIDIA 8800); the way using a texture is possible, too, but not part of the questions I have. The code looks as follows. I've segmented it to make reading easier. Listing 1: To initialize the back buffer just as first operation after context is made current:
::glClearColor(0.5f, 0.6f, 0.8f, 1);
::glClear(GL_COLOR_BUFFER_BIT);
// [#1] ::glReadBuffer(GL_FRONT);
// [#1] ::glDrawBuffer(GL_BACK);
// [#1] ::glRasterPos2f(-1, -1);
// [#1] ::glCopyPixels(0, 0, 1920, 1200, GL_COLOR);
The color set-up here is just used as an indicator later. The lines marked with [#1] will play a role later; they are not neccessary for the original purpose. Listing 2: Allocating of the FBO and RB:
::GLuint fbo;
::glGenFramebuffersEXT(1, &fbo);
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
// allocating render buffer on card
::GLuint framebuffer;
::glGenRenderbuffersEXT(1, &framebuffer);
::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, framebuffer);
::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, 1920, 1200);
::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, framebuffer);
Each function invocations returns "no error", and the FBO tells "complete" if asked for its status. Listing 3: Copying desktop image to FBO:
::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
::glReadBuffer(GL_FRONT);
::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo);
::glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
// [#2] ::glRasterPos2f(-1, -1);
// [#2] ::glCopyPixels(0, 0, 1920, 1200, GL_COLOR);
::glBlitFramebufferEXT(0, 0, 1920, 1200, 0, 0, 1920, 1200, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// [#3] ::glClearColor(0, 0, 0, 1);
// [#3] ::glClear(GL_COLOR_BUFFER_BIT);
AFAIS, here I set the context's front buffer as read target, and the FBO's color attachment 0 as draw target. Each function invocations returns "no error". The lines marked with [#3] show a clearing of the render buffer just for test purposes. (The lines marked with [#2] show the alternative using glCopyPixels instead of BlitFramebuffer.) Listing 4: Copying FBO to back buffer (should fill the back buffer with the desktop image):
::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo);
::glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
::glDrawBuffer(GL_BACK);
// [#2] ::glRasterPos2f(-1, -1);
// [#2] ::glCopyPixels(0, 0, 1920, 1200, GL_COLOR);
::glBlitFramebufferEXT(0, 0, 1920, 1200, 0, 0, 1920, 1200, GL_COLOR_BUFFER_BIT, GL_NEAREST);
AFAIS, here I set the context's back buffer as draw target, and the FBO's color attachment 0 as read target. Each function invocations returns "no error". (The lines marked with [#2] show the alternative using glCopyPixels instead of BlitFramebuffer.) Listing 5: Rendering a dummy object and swapping buffers:
::glColor3f(1.0f, 1.0f, 1.0f);
::glBegin(GL_TRIANGLES);
::glVertex3f( 0.0f, +0.5f, 0.0f);
::glVertex3f(+0.25f, -0.5f, 0.0f);
::glVertex3f(-0.5f, -0.5f, 0.0f);
::glEnd();
// swapping back and front buffers
target->postRender();
Now, executing the program shown above renders a white triangle above blueish background! I would expect to see a white triangle above the desktop image, of course. Activating the lines marked with [#3] shows a white triangle above black background. That means IMO that the copying from the FBO to the back buffer works as expected, but copying from the front buffer to the FBO does not; it copies the back buffer instead. Just to verify this, if the lines marked with [#1] are not commented, the white triangle appears above the desktop image (notice that the blit is still invoked with the front buffer as rerad target)! That is because [#1] makes a front to back buffer copy, of course. Can someone please enlighten me what's wrong? For those that are still interested in (;)), here comes the 2nd approach: Instead of BlitFramebuffer, the lines marked with [#2] can be enabled to use glCopyPixels. Doing so seems to work fine but only until a second rendering is done. E.g adding ... ... Listing 6: Rendering a 2nd dummy object and swapping buffers:
::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo);
::glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
::glDrawBuffer(GL_BACK);
::glRasterPos2f(-1, -1); ::glCopyPixels(0, 0, 1680, 1050, GL_COLOR);
// ::glBlitFramebufferEXT(0, 0, 1920, 1200, 0, 0, 1920, 1200, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// rendering object
::glColor3f(0.5f, 0.5f, 0.5f);
::glBegin(GL_TRIANGLES);
::glVertex3f( 0.0f, +0.25f, 0.0f);
::glVertex3f(+0.125f, -0.25f, 0.0f);
::glVertex3f(-0.25f, -0.25f, 0.0f);
::glEnd();
// swapping back and front buffers
target->postRender();
finally shows a grey triangle above a white triangle above the desktop background. The fact that the white triangle is still visible means IMO that the glReadBuffer command addresses the front buffer but not the specified color attachment of the FBO. Maybe I misunderstand something w.r.t. FBOs and glReadBuffer, or I miss some necessary settings. There is a mysterious "pixel ownership" issue, but I have the impression that it isn't the problem here?! Thank you for reading. Awaiting for answers ... :) [Edited by - haegarr on April 12, 2010 2:01:03 PM]

explicit instantiation in C++

10 February 2006 - 07:07 AM

I have a class representing an affine map (say a homogeneous matrix allowed to be changed only in an affine transformation compatible way). However, the AffineMap is generic with the scalar type. It provides a static const predefined instance named IDENTITY. The default c'tor should initialize like the identity map. And I use explicit instantiation.
// ===== in the primary header file:

template<typename scalar_g>
class AffineMap3 {

public: // x'tors

   AffineMap3();

public: // predefined instances

   static const AffineMap3<scalar_g> IDENTITY;

};

extern template class AffineMap3<float>;

// ===== in the secondary header file (which includes the primary header):

template<typename scalar_g>
AffineMap3<scalar_g>::AffineMap3()
:  _b0(1,0,0),_s0(0),
   _b1(0,1,0),_s1(0),
   _b2(0,0,1),_s2(0),
   _p(0,0,0),_s3(1) { }

// ===== in the implementation file (which includes the secondary header):

template<>
const AffineMap3<float>
AffineMap3<float>::IDENTITY;

template class AffineMap3<float>;


This causes an "undefined reference" for AffineMap<float>::IDENTITY error using either gcc 3.3.5 (linux) and 4.0.0 (MacOS X). Just exchanging the lines in the implementation file
template class AffineMap3<float>;

template<>
const AffineMap3<float>
AffineMap3<float>::IDENTITY;


causes gcc 3.3.5 (linux) to be quiet, but gcc 4.0.0 (MacOS X) still complains the undefined symbol. Writing the empty function parantheses at the instance is not a solution, since the compiler complains IDENTITY being an unknown function. However, _this_ is a working solution:
// ===== in the primary header file:

template<typename scalar_g>
class AffineMap3 {

public: // x'tors

   AffineMap3(bool dummy =false);

public: // predefined instances

   static const AffineMap3<scalar_g> IDENTITY;

};

extern template class AffineMap3<float>;

// ===== in the secondary header file (which includes the primary header):

template<typename scalar_g>
AffineMap3<scalar_g>::AffineMap3(bool)
:  _b0(1,0,0),_s0(0),
   _b1(0,1,0),_s1(0),
   _b2(0,0,1),_s2(0),
   _p(0,0,0),_s3(1) { }

// ===== in the implementation file (which includes the secondary header):

template<>
const AffineMap3<float>
AffineMap3<float>::IDENTITY(false);

template class AffineMap3<float>;


Could anybody tell please me what the correct way/syntax would be to do such a thing? Thx.

PARTNERS