Bringing OpenGL C/C++ code to the web with FlasCC

Stage3D allows GPU accelerated 3D content to run in the Flash Player accross operating systems and browsers. We have a number of interesting libraries that will help you bring your OpenGL C/C++ code to the web with FlasCC.

GLS3D

The GLS3D library is an open source project we started to provide a basic OpenGL implementation for FlasCC users targeting Stage3D.

Source Code: https://github.com/adobe/gls3d
Live Demo: http://cmodule.org/neverball

FreeGLUT

The GLUT library was created to make it easier to write cross-platform OpenGL based apps. I’ve implemented a Stage3D backend for the FreeGLUT library and used it in conjunction with the GLS3D project to compile some of the popular NeHe OpenGL tutorials.

Source Code: https://github.com/alexmac/alcfreeglut
Live Demo: http://www.cmodule.org/nehe/

GLSL To AGAL

If you’ve investigated the Stage3D API you’ll know that the shader format is a custom bytecode format designed to be easily compiled down to DirectX bytecode or GLSL depending on the platform the Flash Player is running on. Sadly this makes it hard for humans to write. This project is based on the open-source Mesa codebase and contains a full GLSL parser and optimizer hooked up to a custom AGAL backend so that GLSL shaders can be compiled and optimized down to AGAL bytecode. It can be used offline as a pre-processing step within your applications asset creation workflow or at runtime by compiling the library to a SWC with FlasCC and using it in your SWF.

The repository also includes a precompiled SWC so that you can get started with it immediately.

Source Code: https://github.com/adobe/glsl2agal
Live Demo: http://adobe.github.com/glsl2agal/

Starling Filter Playground

Starling 1.2 supports AGAL based filters that can be applied to any Sprite to alter the way they render. Rather than writing the filter by hand with AGAL asm its possible to hook up the GLSL2AGAL project to Starling so that these Filters can be written using GLSL. Modifying the shader in the UI causes the filter to update in realtime.

Source Code: https://github.com/alexmac/StarlingFilterPlayground
Live Demo: http://alexmac.github.com/StarlingFilterPlayground/

One Response to Bringing OpenGL C/C++ code to the web with FlasCC

  1. Yueqi says:

    I am using the FreeGLUT demo to learn flascc compiling and the performance of the corresponding swf file. I noticed that the Nehe demos in swf format do not support mouse function, although the keyboard callback is fully supported. I’ve tried to add glutMouseFunc and glutMotionFunc to Lesson08. When the code was compiled under vs2010, the generated .exe have the capacity to handle the mouse function properly. However, when it was compiled in flascc with the makefile shown in FreeGLUT demos. It DOESNOT work at all. Any idea how to make the mouse work properly in flascc?
    Here’s the source code that can run in vs2010. Slash out the “#include ” will make it pass the compiling in flascc.
    ———————————————————————————-
    #include
    #include
    #include
    #include
    #include
    #include “tgaload.h”

    #define MAX_NO_TEXTURES 3

    #define CUBE_TEXTURE 0
    #define FCUBE_TEXTURE 1
    #define MCUBE_TEXTURE 2

    GLuint texture_id[MAX_NO_TEXTURES];

    int old_x=0;
    int old_y=0;
    int valid=0;
    float Base_Rot_X;
    float Base_Rot_Y;
    float Base_Rot_Z;
    float xrot;
    float yrot;
    float xspeed; // X Rotation Speed
    float yspeed; // Y Rotation Speed
    float ratio;
    float z=-5.0f; // Depth Into The Screen

    GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };
    GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
    GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };

    GLuint filter; // Which Filter To Use
    bool light; // Lighting ON/OFF
    bool blend; // Blending OFF/ON? ( NEW )
    bool lp; // L Pressed?
    bool fp; // F Pressed?
    bool bp; // B Pressed? ( NEW )

    void LoadGLTextures (void)
    {
    glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
    glGenTextures (3, texture_id);

    image_t temp_image;

    glBindTexture ( GL_TEXTURE_2D, texture_id [0] );
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    tgaLoad ( “glass.tga”, &temp_image, TGA_FREE | TGA_LOW_QUALITY );

    glBindTexture ( GL_TEXTURE_2D, texture_id [1] );
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    tgaLoad ( “glass.tga”, &temp_image, TGA_FREE | TGA_LOW_QUALITY );

    glBindTexture ( GL_TEXTURE_2D, texture_id [2] );
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST );
    tgaLoad ( “glass.tga”, &temp_image, TGA_FREE | TGA_LOW_QUALITY );
    }

    void init(void)
    {
    LoadGLTextures();
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH); // Enable Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
    glClearDepth(1.0f); // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST); // Enables Depth Testing
    glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
    //ShowCursor(false);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
    glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
    glEnable(GL_LIGHT1); // Enable Light One

    glColor4f(1.0f, 1.0f, 1.0f, 0.5); // Full Brightness. 50% Alpha
    glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For Translucency

    }

    void reshape( int w, int h )
    {
    // Prevent a divide by zero, when window is too short
    // (you cant make a window of zero width).
    if(h == 0)
    h = 1;

    ratio = 1.0f * w / h;
    // Reset the coordinate system before modifying
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Set the viewport to be the entire window
    glViewport(0, 0, w, h);

    // Set the clipping volume
    gluPerspective(80,ratio,1,200);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0, 30,
    0,0,10,
    0.0f,1.0f,0.0f);
    }

    void display( void )
    {
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glLoadIdentity ( );

    glPushMatrix();
    glTranslatef ( 0.0, 0.0, z );
    glRotatef ( xrot, 1.0, 0.0, 0.0 );
    glRotatef ( yrot, 0.0, 1.0, 0.0 );

    glBindTexture ( GL_TEXTURE_2D, texture_id[filter] );

    glBegin ( GL_QUADS );
    // Front Face
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
    // Back Face
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
    // Top Face
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
    // Bottom Face
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
    // Right face
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
    // Left Face
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
    glEnd();
    glPopMatrix();
    xrot+=xspeed;
    yrot+=yspeed;

    glutSwapBuffers();
    }

    void keyboard ( unsigned char key, int x, int y ) // Create Keyboard Function
    {
    switch ( key ) {
    case 27: // When Escape Is Pressed…
    exit ( 0 ); // Exit The Program
    break; // Ready For Next Case
    case ‘f’:
    fp=true;
    filter+=1;
    if (filter>2)
    {
    filter=0;
    }
    break;
    case ‘l’:
    lp=true;
    light=!light;
    if (!light)
    {
    glDisable(GL_LIGHTING);
    }
    else
    {
    glEnable(GL_LIGHTING);
    }
    break;
    case ‘b’:
    bp=true;
    blend = !blend;
    if(blend)
    {
    glEnable(GL_BLEND); // Turn Blending On
    glDisable(GL_DEPTH_TEST); // Turn Depth Testing Off
    }
    else
    {
    glDisable(GL_BLEND); // Turn Blending Off
    glEnable(GL_DEPTH_TEST); // Turn Depth Testing On
    }
    break;

    default: // Now Wrap It Up
    break;
    }
    }

    void arrow_keys ( int a_keys, int x, int y ) // Create Special Function (required for arrow keys)
    {
    switch ( a_keys ) {
    case GLUT_KEY_UP: // When Up Arrow Is Pressed…
    xspeed-=0.01f;
    break;
    case GLUT_KEY_DOWN: // When Down Arrow Is Pressed…
    xspeed+=0.01f;
    break;
    case GLUT_KEY_RIGHT:
    yspeed+=0.01f;
    break;
    case GLUT_KEY_LEFT:
    yspeed-=0.01f;
    break;
    case GLUT_KEY_F1:
    glutFullScreen ();
    break;
    case GLUT_KEY_F2:
    glutReshapeWindow ( 500, 500 );
    break;
    default:
    break;
    }
    }
    void mousebutton(int button,int state,int x,int y)
    {
    switch(button)
    {
    //click the left button to let the object move
    case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN)
    {
    valid = 1;
    old_x=x;
    old_y=y;
    valid = 1;
    Base_Rot_X = xrot;
    Base_Rot_Y = yrot;
    // Base_Rot_Z = Camera.rot.z;
    }
    break;
    //click the right button to let the object stop moving
    case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN)
    {

    }
    break;
    default:
    break;
    }
    }
    void mousemotion(int x, int y)
    {
    if (valid==1)
    {
    int dx = x – old_x;
    int dy = y – old_y;
    /* do something with dx and dy */
    yrot = Base_Rot_Y + (float)dx;
    }

    }
    int main ( int argc, char** argv ) // Create Main Function For Bringing It All Together
    {
    glutInit ( &argc, argv ); // Erm Just Write It =)
    glutInitDisplayMode ( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA ); // Display Mode
    glutInitWindowPosition (0,0);
    glutInitWindowSize ( 500, 500 ); // If glutFullScreen wasn’t called this is the window size
    glutCreateWindow ( “NeHe Lesson 6- Ported by Rustad” ); // Window Title (argv[0] for current directory as title)
    init ();
    // glutFullScreen ( ); // Put Into Full Screen
    glutDisplayFunc ( display ); // Matching Earlier Functions To Their Counterparts
    glutReshapeFunc ( reshape );
    glutKeyboardFunc ( keyboard );
    glutSpecialFunc ( arrow_keys );
    glutIdleFunc ( display );
    glutMouseFunc(mousebutton);
    glutMotionFunc(mousemotion);
    glutMainLoop ( ); // Initialize The Main Loop
    }