I'm still trying to implement the glblendfuncseparate and glblendequationseparate (and fix glblendcolor) functions. Since I couldn't find a demo which tests these extensions, I figured I'd modify some demo, and this one, http://www.sgi.com/software/opengl/advanced97/programs/multialphablend.c looked like it should be easy to modify so that the different functions/equations for rgb and alpha actually make a difference.
Unfortunately there are some strange problems even without the new extensions (and without the new driver code), for instance when the blend equation in this demo is set to GL_MIN, then everything is rendered completely black - even when the demo is changed so that blending is never enabled! With software mesa it works just fine.
Any ideas what could be going on, the mesa blendeq demo works correctly interstingly.
(I've changed the multialphablend demo slightly, otherwise it wouldn't even compile. I hope it isn't somehow ill-specified.)


Roland
/*
 *  multialphablend.c
 *  Celeste Fowler, 1997
 *
 *  An example of using alpha-blending to render multiple transparent
 *  objects (with sorting).
 *
 */

#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>

#ifdef _WIN32
#include <sys/timeb.h>
#else
#include <sys/time.h>
#endif

GLUquadricObj *cone, *base, *qsphere;

#ifdef _WIN32
#define trunc(x) ((double)((int)(x)))

int
gettimeofday(struct timeval* tp)
{
  struct timeb tb;

  ftime(&tb);
  tp->tv_sec = tb.time;
  tp->tv_usec = tb.millitm * 1000;

  /* 0 indicates that the call succeeded. */
  return 0;
}
#endif

void Init(void)
{
  static GLfloat lightpos[] = {.5, .75, 1.5, 1};

  glEnable(GL_DEPTH_TEST); 
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);

  glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

  cone = gluNewQuadric();
  base = gluNewQuadric();
  qsphere = gluNewQuadric();

/*  glBlendEquationSeparateEXT(GL_MIN, GL_MAX);*/
  glBlendEquation(GL_MIN);
/*  glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE, GL_ONE);*/
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void Reshape(GLsizei w, GLsizei h)
{
  glViewport(0, 0, w, h);
  
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(60, 1, .01, 10);
  gluLookAt(0, 0, 2.577, 0, 0, -5, 0, 1, 0);
  
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

void draw_room(void)
{
  /* material for the walls, floor, ceiling */
  static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f};

  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);

  glBegin(GL_QUADS);
  
  /* floor */
  glNormal3f(0, 1, 0);
  glVertex3f(-1, -1, 1);
  glVertex3f(1, -1, 1);
  glVertex3f(1, -1, -1);
  glVertex3f(-1, -1, -1);

  /* ceiling */
  glNormal3f(0, -1, 0);
  glVertex3f(-1, 1, -1);
  glVertex3f(1, 1, -1);
  glVertex3f(1, 1, 1);
  glVertex3f(-1, 1, 1);  

  /* left wall */
  glNormal3f(1, 0, 0);
  glVertex3f(-1, -1, -1);
  glVertex3f(-1, -1, 1);
  glVertex3f(-1, 1, 1);
  glVertex3f(-1, 1, -1);

  /* right wall */
  glNormal3f(-1, 0, 0);
  glVertex3f(1, 1, -1);
  glVertex3f(1, 1, 1);
  glVertex3f(1, -1, 1);
  glVertex3f(1, -1, -1);

  /* far wall */
  glNormal3f(0, 0, 1);
  glVertex3f(-1, -1, -1);
  glVertex3f(1, -1, -1);
  glVertex3f(1, 1, -1);
  glVertex3f(-1, 1, -1);

  glEnd();
}

void draw_cone(void)
{
  static GLfloat cone_mat[] = {0.f, .5f, 1.f, .5f};

  glPushMatrix();
  glTranslatef(0, -1, 0);
  glRotatef(-90, 1, 0, 0);

  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);

  /* base is coplanar with floor, so turn off depth testing */
  glDisable(GL_DEPTH_TEST);
  gluDisk(base, 0., .3, 20, 1); 
  glEnable(GL_DEPTH_TEST);

  gluCylinder(cone, .3, 0, 1.25, 20, 1);

  glPopMatrix();
}

void draw_sphere(GLdouble angle)
{
  static GLfloat sphere_mat[] = {1.f, .5f, 0.f, .5f};

  glPushMatrix();
  glTranslatef(0, -.3, 0);
  glRotatef(angle, 0, 1, 0);
  glTranslatef(.6, 0, 0);

  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  gluSphere(qsphere, .3, 20, 20);

  glPopMatrix();
}

GLdouble get_msecs(void)
{
  struct timeval t;
  struct timezone tz;
  gettimeofday(&t, &tz);
  return ((t.tv_sec % 5)*1000 + t.tv_usec / 1000.);
}

void Draw(void)
{
    GLenum err;
    GLdouble secs, degrees;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /* one revolution every 5 seconds... */
    secs = get_msecs();
    degrees = (secs/1000.) * (360.) / 5.;

    draw_room();

    glEnable(GL_BLEND);
    glEnable(GL_CULL_FACE);
    if (degrees < 180) {
      /* sphere behind cone */
      glCullFace(GL_FRONT);
      draw_sphere(degrees);
      draw_cone();
      glCullFace(GL_BACK);
      draw_sphere(degrees);
      draw_cone();
    } else {
      /* cone behind sphere */
      glCullFace(GL_FRONT);
      draw_cone();
      draw_sphere(degrees);
      glCullFace(GL_BACK);
      draw_cone();
      draw_sphere(degrees);
    }
    glDisable(GL_CULL_FACE);
    glDisable(GL_BLEND);

    err = glGetError();
    if (err != GL_NO_ERROR) printf("Error:  %s\n", gluErrorString(err));

    glutSwapBuffers();
}

void Key(unsigned char key, int x, int y)
{
  static int idle = 1;
  if (key == 27) exit(0);
  idle = (idle == 0);
  if (idle) {
    glutIdleFunc(Draw);
  } else {
    glutIdleFunc(0);
  }

}

void Visible(int state)
{
    if (state == GLUT_VISIBLE)
        glutIdleFunc(Draw);
    else
        glutIdleFunc(NULL);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(512, 512);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
    glutCreateWindow(argv[0]);
    glutReshapeFunc(Reshape);
    glutKeyboardFunc(Key);
    glutDisplayFunc(Draw);
    glutVisibilityFunc(Visible);

    Init();
    glutMainLoop();
    return 0;
}

Reply via email to