Order of the Butterfly
Posts: 171 from 2006/10/6
From: Spain
I have some problems with tinygl using generated textures with alpha, but i guess that is a depth buffer problem because sometimes the zone of texture with alpha is drawed properly, but it draws the background color sometimes, i revised all code, i checked my 2d engine in opengl for iphone to check if there is something i forgot, i searched on google dozens of webs without any result. Maybe someone see the error, i don't have any idea on this moment. Here is the code and makefile:
Makefile:
Code:
CC = gcc
LD = ld
STRIP = strip
CFLAGS = -O1 -s -fomit-frame-pointer -noixemul -ISDK:tinygl-sdk/include
NOSTARTUPFILES = 1
#GOTO = 1
REMOVE = 1
ifdef NOSTARTUPFILES
CFLAGS+= -DNOSTARTUPFILES -nostartfiles
endif
ifdef GOTO
CFLAGS+= -DGOTO
endif
ifdef REMOVE
CFLAGS+= -DREMOVE
endif
INTRO_OBJS = intro.o
all: intro
intro: $(INTRO_OBJS)
$(CC) $(CFLAGS) -o $@ $(INTRO_OBJS)
$(STRIP) -s -R .comment -R .gnu.version -R .gnu.version_d -R .gnu.version_r $@
chmod u+x $@
intro_map:
$(CC) $(CFLAGS) intro.c -Wl,-Map=foobar.map,--traditional-format
clean:
rm -f *.o intro
intro.c:
Code:
/*
* 4Kb Intro startup by Pedro Gil (Balrog Soft)
* www.amigaskool.net
*
* TinyGL and AHI device startup code,
* and music synth for 4k intros.
* The song was ripped from howagen intro by tonic.
*
* Special thanks to Piru for his small opts,
* and Morphzone.org people!
*
*/
#include <devices/ahi.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/tinygl.h>
#include <proto/ahi.h>
#include <stdio.h>
#define FREQUENCY 8000
#define TYPE AHIST_M8S
#define BUFFERSIZE 24000
#define TONEFREQ 440.0f
#define TONEBASE 1.059463094359f
#define TONEBYTES 2047
#define CHANELS 3
#define WAVE_SAWTOOTH 0
#define WAVE_SQUARE 1
#define VOL_DECAY -1
#define VOL_MAX 32
#ifndef M_PI
#define M_PI 3.14159265
#define M_PI2 6.283185
#endif
#define MAX_PARTICLES 32
#define sawtooth(O,D) ((O - 32) * D) >> 4
#define square(O,D) (((O&31) < 16 ? 31 : -32) * D) >> 4
static void display(void);
#ifndef GOTO
static void fill_buffer(void);
#endif
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
struct Library *TinyGLBase;
GLContext *__tglContext;
static struct MsgPort *AHImp = NULL;
static struct AHIRequest *AHIios1 = NULL;
static struct AHIRequest *AHIios2 = NULL;
static struct AHIRequest *link = NULL;
static struct Task *self;
static GLuint texture[1]; // Storage For Our Particle Texture
static GLfloat vertex [MAX_PARTICLES*18];
static GLfloat texcoords[MAX_PARTICLES*12];
static LONG tex[32 * 32];
static BYTE AHIDevice = -1, ch;
static BYTE buffer1[BUFFERSIZE], buffer2[BUFFERSIZE], vol[CHANELS], wave[CHANELS];
static BYTE *p1=buffer1, *p2=buffer2;
static void *tmp;
static BOOL init = TRUE;
static ULONG signals;
static FLOAT anote[CHANELS], freq[CHANELS];
static LONG i, j, tbuf = 0, track_note = 0,
m_w = 19298, m_z = 84729;
static char cnote[CHANELS];
static char *song[] = {"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@EEHGHJHGAAHGHJHGCCJHJLJHEHGHJH"
"GDEELJJJHHEEJHHHGGCCJHHHGGEEDEEEGGE@EGJHGEA@AHJLHGC@CJLJHGEHGHJ"
"LHGE ",
"QQXQQXQXMMTMMTMTOOVOOVOVLLSLLSLS ",
"EEEEEEEEHEEEEEEEJEEEEEEELEEEEEEE "};
#define __TEXTSECTION__ __attribute__((section(".text")))
#ifdef NOSTARTUPFILES
int entry(void)
#else
int main(void)
#endif
{
SysBase = *(struct ExecBase **) 4;
DOSBase = OpenLibrary("dos.library", 50);
TinyGLBase = OpenLibrary("tinygl.library", 50);
if (TinyGLBase)
{
self = FindTask(NULL);
// Initialize AHI device
AHImp=CreateMsgPort();
#ifndef REMOVE
if(AHImp != NULL)
{
#endif
AHIios1 = (struct AHIRequest *) CreateIORequest(AHImp, sizeof(struct AHIRequest));
AHIios1->ahir_Version = 4;
AHIDevice = OpenDevice(AHINAME, 0, (struct IORequest *)AHIios1, 0);
#ifndef REMOVE
}
#endif
// Make a copy of the request (for double buffering)
AHIios2 = AllocMem(sizeof(struct AHIRequest), MEMF_ANY);
CopyMem(AHIios1, AHIios2, sizeof(struct AHIRequest));
// Configure synth chanels
vol[0] = 16;
vol[1] = VOL_DECAY;
vol[2] = VOL_DECAY;
wave[0] = WAVE_SQUARE;
wave[1] = WAVE_SAWTOOTH;
wave[2] = WAVE_SAWTOOTH;
__tglContext = GLInit();
if (__tglContext)
{
glutInit(NULL,NULL);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
#ifndef REMOVE
glutInitWindowSize(640, 480);
#endif
glutFullScreen();
glutCreateWindow(NULL);
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
// Enable depth test
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
// Enable blending function
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFunc(GL_SRC_ALPHA,GL_ONE);
// Create texture
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture[0]);
LONG n;
for (i = 0; i < 32; i++)
{
for (j = 0; j < 32; j++)
{
n = (i-16)+(j-16);
if (n > -24 & n < 24)
tex[i*32+j] = 0xffffffff;
else
tex[i*32+j] = 0x00000000;
}
}
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 32, 32, 0, GL_BGRA, GL_UNSIGNED_BYTE, tex);
glBindTexture(GL_TEXTURE_2D, texture[0]);
// Create vertex and texture coords arrays
for (i = 0; i < MAX_PARTICLES; i++)
{
GLfloat x = (rand()%10-5)*1.5f;
GLfloat y = (rand()%10-5)*1.5f;
GLfloat z = ((rand()%10-5)-40)*1.0f;
FLOAT s = (rand()%10)*0.5f;
n = i * 18;
vertex[n] = x+0.5f*s;
vertex[n+1] = y+0.5f*s;
vertex[n+2] = z;
vertex[n+3] = x-0.5f*s;
vertex[n+4] = y+0.5f*s;
vertex[n+5] = z;
vertex[n+6] = x+0.5f*s;
vertex[n+7] = y-0.5f*s;
vertex[n+8] = z;
vertex[n+9] = x-0.5f*s;
vertex[n+10] = y+0.5f*s;
vertex[n+11] = z;
vertex[n+12] = x+0.5f*s;
vertex[n+13] = y-0.5f*s;
vertex[n+14] = z;
vertex[n+15] = x-0.5f*s;
vertex[n+16] = y-0.5f*s;
vertex[n+17] = z;
n = i * 12;
texcoords[n] = 1.0f;
texcoords[n+1] = 1.0f;
texcoords[n+2] = 0.0f;
texcoords[n+3] = 1.0f;
texcoords[n+4] = 1.0f;
texcoords[n+5] = 0.0f;
texcoords[n+6] = 0.0f;
texcoords[n+7] = 1.0f;
texcoords[n+8] = 1.0f;
texcoords[n+9] = 0.0f;
texcoords[n+10] = 0.0f;
texcoords[n+11] = 0.0f;
}
// Enable client state for vertex and texture coords
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Set projecto matrix
glMatrixMode(GL_PROJECTION);
gluPerspective(80, 640.0 / 480.0, 1.0, 500.0);
glMatrixMode(GL_MODELVIEW);
// Set pointers to arrays
glVertexPointer(3, GL_FLOAT, 0, vertex);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
glutIdleFunc(display);
glutMainLoop();
GLClose(__tglContext);
}
// Abort any pending iorequests
AbortIO((struct IORequest *) AHIios1);
WaitIO((struct IORequest *) AHIios1);
if(link) // Only if the second request was started
{
AbortIO((struct IORequest *) AHIios2);
WaitIO((struct IORequest *) AHIios2);
}
CloseLibrary(TinyGLBase);
CloseLibrary(DOSBase);
}
return 0;
}
static void display(void)
{
// Ahi device handle code
// Send io request to the device
if ((signals & (1L << AHImp->mp_SigBit) || init))
{
if (init && link)
init = FALSE;
if (!link)
#ifdef GOTO
{
tmp = &&ret1;
goto synth;
}
ret1:
#else
fill_buffer();
ret1:
#endif
AHIios1->ahir_Std.io_Message.mn_Node.ln_Pri = 0;
AHIios1->ahir_Std.io_Command = CMD_WRITE;
AHIios1->ahir_Std.io_Data = p1;
AHIios1->ahir_Std.io_Length = BUFFERSIZE;
AHIios1->ahir_Std.io_Offset = 0;
AHIios1->ahir_Frequency = FREQUENCY;
AHIios1->ahir_Type = TYPE;
AHIios1->ahir_Volume = 0x10000; // Full volume
AHIios1->ahir_Position = 0x8000; // Centered
AHIios1->ahir_Link = link;
SendIO((struct IORequest *) AHIios1);
}
// Check if there are any signals from ahi device
if(link)
{
// Send a fake signal to not stop the loop
Signal(self, SIGBREAKF_CTRL_D);
signals = Wait(SIGBREAKF_CTRL_D | (1L << AHImp->mp_SigBit));
}
link = AHIios1;
// Swap ahi buffers
if ((signals & (1L << AHImp->mp_SigBit)) || init)
{
if (!init)
WaitIO((struct IORequest *) AHIios2);
// Swap buffer and request pointers, and restart
tmp = p1;
p1 = p2;
p2 = tmp;
#ifdef GOTO
tmp = &&ret2;
goto synth;
ret2:
#else
fill_buffer();
#endif
tmp = AHIios1;
AHIios1 = AHIios2;
AHIios2 = tmp;
}
// TinyGL stuff goes here
// Clear Screen And Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glLoadIdentity();
glTranslatef(0.0f,0.0f,-40.0f);
glRotatef(0.5f, 0.0f, 1.0f, 0.0f);
glTranslatef(0.0f,0.0f,40.0f);
glDrawArrays(GL_TRIANGLES, 0, MAX_PARTICLES*6);
glutSwapBuffers();
#ifdef GOTO
return;
// Synth code for testing
synth:
// Copy synth code here!!!
goto *tmp;
#endif
}
#ifndef GOTO
static void fill_buffer(void)
{
LONG n;
SHORT decay, note, note_pos;
for (n = 0; n < BUFFERSIZE; n++)
{
// Check the position in the buffer
note_pos = ((tbuf + n + 1) & TONEBYTES);
note = 0;
// Calculate decay level
decay = (1024 - (note_pos - 1024))>>6;
if (decay < 0)
decay = 0;
for (ch = 0; ch < CHANELS; ch++)
{
if (note_pos == 0)
{
// Set base frequency
freq[ch] = TONEBASE;
// Increments the track note to be played
if (ch == 0)
track_note ++;
// And get the notes to play
char pnote = song[ch][track_note % strlen(song[ch])]-64;
if (pnote != cnote[ch])
{
cnote[ch] = pnote;
anote[ch] = 0;
}
// Get the frequency for the note to be played
for (j = 1; j < cnote[ch]; j ++)
freq[ch] *= TONEBASE;
if (cnote[ch] == 0)
freq[ch] = 0;
freq[ch] = (TONEFREQ * freq[ch]) / 512;
}
// Increase the note frequency to complete a wave
anote[ch] += freq[ch];
// Generate waves with sawtooth and square oscilators
// Decay can be used to set a volume
BYTE vol_ch = vol[ch] < 0 ? decay : vol[ch],
osc = (BYTE)anote[ch] & 63;
if (wave[ch] == WAVE_SAWTOOTH)
note += sawtooth(osc, vol_ch) % 32;
else if (wave[ch] == WAVE_SQUARE)
note += square(osc, vol_ch) % 32;
}
//printf(" %hin",decay);
if (note > 127)
note = 127;
else if (note < -128)
note = -128;
// Store wave on buffer
p1[n] = note;
}
tbuf += BUFFERSIZE;
}
#endif
#ifdef NOSTARTUPFILES
/* __abox__ symbol is required or else the binary is loaded as PowerUP app */
const int __abox__ __TEXTSECTION__ = 1;
#endif
Balrog Software -
AmigaSkool.netMac Mini - MorphOS 3.8 - G4 1.5Ghz - Ati 9200 64 Mb
Efika - MorphOS 3.6 - Ati 9200 64Mb - 80 Gb HD
Amiga 1200D - OS 3.9 - Blizzard 603e/240mh