Mandelbrot on GPU

hello,
i don’t know if im on the right place here but i’ll ask:
i have to program the mandelbrot set for my study.
But i have no experience in C-programming so that i need a compelte simple code with grapical output which runs on the gpu. without zoom etc…

i think it gives many complete code for the mandelbrot in Cg but i haven’t found.

please help me.
thanks!!!

I think I have seen Mandelbrot demo in some SDK. Probably it was ATI SDK

hi, thx for this answer first!
yes it’s in the NVIDIA SDK, too.
but i need a simple code. not a huge code like this.

:slight_smile:

???

I just sheded some smiles :slight_smile:

In the book OpenGL shading language there’s an exemple about that. I don’t know if it has been released on the book’s website.

See “mandelbrot.c” here:
http://gitweb.freedesktop.org/?p=mesa/me…-1;f=progs/glsl

It’s a test program using the shaders from the OpenGL orange book.

-Brian

Here’s a quick-and-dirty GL2.0 mandelbrot/julia explorer that I wrote a while back using GLUT:

//
// psmand - gl2.0 mandelbrot/julia shader demo
//
// Author: Edward Hutchins, Jan 2006
// License: Public Domain
//

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glut.h>

static const GLint SCREEN_W = 600;
static const GLint SCREEN_H = 600;
static const GLfloat NEAR_W = 0.1;
static const GLfloat FAR_W = 10.0;

static GLint screen_w = SCREEN_W;
static GLint screen_h = SCREEN_H;

// mandelbrot center
static GLfloat cx = 0;
static GLfloat cy = -0.5;
// zoom to edges of rect
static GLfloat zoom = 1.5;

// mandelbrot shader
static GLuint hMandProg = 0;
// julia shader
static GLuint hJuliaProg = 0;
// uniform seed
static GLint julia_c_pos = 0;

static bool bDragging = false;
static int nDragPt[2];
static bool bJuliaing = false;
static int nJuliaPt[2];

#define FAIL(x) do { printf x; printf( "
" ); exit( 1 ); } while (0)

void display()
{
    glClearColor( 0, 0, 0, 1 );
    glClear( GL_COLOR_BUFFER_BIT );

    glColor4f( 1, 0, 0, 1 );

    GLfloat left = cx - zoom;
    GLfloat right = cx + zoom;
    GLfloat top = cy - zoom;
    GLfloat bottom = cy + zoom;

    glBegin( GL_TRIANGLE_STRIP );
	glTexCoord2f( left, bottom );
	glVertex2f( -1, -1 );

	glTexCoord2f( right, bottom );
	glVertex2f( 1, -1 );

	glTexCoord2f( left, top );
	glVertex2f( -1, 1 );

	glTexCoord2f( right, top );
	glVertex2f( 1, 1 );
    glEnd();

    glutSwapBuffers();
}

void make_tex()
{
    const int TEX_SIZE = 1024;
    GLfloat tex[TEX_SIZE][4];

    // create a rainbow lookup table for coloring the iteration count
    // (could be any function you like)
    for (int x = 0; x < TEX_SIZE - 1; ++x)
    {
	float f = 3.1415927 * x / TEX_SIZE;
	float c = cos( f );
	float s = sin( f );
	tex[x][0] = 1 - c;
	tex[x][1] = s * s;
	tex[x][2] = c;
	tex[x][3] = 1;
    }
    tex[TEX_SIZE - 1][0] = tex[TEX_SIZE - 1][1] = tex[TEX_SIZE - 1][2] = tex[TEX_SIZE - 1][3] = 0;

    glTexImage1D( GL_TEXTURE_1D, 0, GL_RGBA, TEX_SIZE, 0, GL_RGBA, GL_FLOAT, tex );
}

GLuint make_frag_prog( const GLchar *pcszShader )
{
    GLuint hShader = glCreateShader( GL_FRAGMENT_SHADER );
    if (!hShader) FAIL(( "Can't create shader!" ));

    const GLchar *ppcszShader[1] = { pcszShader };

    glShaderSource( hShader, 1, ppcszShader, NULL );
    glCompileShader( hShader );
    GLint nStatus;
    glGetShaderiv( hShader, GL_COMPILE_STATUS, &nStatus );
    if (!nStatus)
    {
    	char szBuff[10240];
	glGetShaderInfoLog( hShader, sizeof(szBuff), NULL, szBuff );
	FAIL(( "Shader failed to compile:
%s", szBuff ));
    }
    else printf( "Shader compiled okay!
" );

    GLuint hProgram = glCreateProgram();
    if (!hProgram) FAIL(( "Can\'t create program!" ));

    glAttachShader( hProgram, hShader );

    glLinkProgram( hProgram );
    glGetProgramiv( hProgram, GL_LINK_STATUS, &nStatus );
    if (!nStatus)
    {
    	char szBuff[10240];
	glGetProgramInfoLog( hProgram, sizeof(szBuff), NULL, szBuff );
	FAIL(( "Program failed to link:
%s", szBuff ));
    }
    else printf( "Program linked okay!
" );

    return( hProgram );
}

void init()
{
    make_tex();

    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
    glEnable( GL_TEXTURE_1D );

    //glAlphaFunc( GL_GEQUAL, 0.5 );
    //glEnable( GL_ALPHA_TEST );

    hMandProg = make_frag_prog(
    	"uniform sampler1D myTexture;
"
	"void main( void )
"
	"{
"
	"   // swap x,y on texcoords to get nice orientation (should be via viewport)
"
	"   vec2 p; p.x = p.y = 0;
"
    	"   vec2 c = vec2( gl_TexCoord[0].yx );
"
	"   float iters = 0;
"
	"   while ((iters < 1) && (dot( p, p ) < 4))
"
	"   {
"
	"   	float nx = p.x * p.x - p.y * p.y + c.x;
"
	"   	float ny = 2 * p.x * p.y + c.y;
"
	"   	p.x = nx; p.y = ny;
"
	"   	iters += 1 / 255.0;
"
	"   }
"
	"   gl_FragColor = texture1D( myTexture, iters );
"
	"}
"
    );

    hJuliaProg = make_frag_prog(
    	"uniform sampler1D myTexture;
"
    	"uniform vec2 c;
"
	"void main( void )
"
	"{
"
	"   // swap x,y on texcoords to get nice orientation (should be via viewport)
"
	"   vec2 p = vec2( gl_TexCoord[0].yx );
"
	"   float iters = 0;
"
	"   while ((iters < 1) && (dot( p, p ) < 4))
"
	"   {
"
	"   	float nx = p.x * p.x - p.y * p.y + c.x;
"
	"   	float ny = 2 * p.x * p.y + c.y;
"
	"   	p.x = nx; p.y = ny;
"
	"   	iters += 1 / 255.0;
"
	"   }
"
	"   gl_FragColor = texture1D( myTexture, iters );
"
	"}
"
    );

    julia_c_pos = glGetUniformLocation( hJuliaProg, "c" );
    if (julia_c_pos < 0)
    {
	FAIL(( "Failed find julia shader \"c\" uniform!
" ));
    }
    printf( "julia_c_pos = %d!
", julia_c_pos );

    glUseProgram( hMandProg );
}

void reshape( int w, int h )
{
    screen_w = w;
    screen_h = h;

    glViewport( 0, 0, w, h );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho( -1, 1, -1, 1, -1, 1 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

static void motion( int x, int y )
{
    if (bDragging)
    {
    	int dx = x - nDragPt[0];
    	int dy = y - nDragPt[1];
	cx -= (2 * zoom / screen_w) * dx;
	cy -= (2 * zoom / screen_h) * dy;
    	nDragPt[0] = x;
    	nDragPt[1] = y;
	glutPostRedisplay();
    }
    
    if (bJuliaing)
    {
    	int dx = x - nJuliaPt[0];
    	int dy = y - nJuliaPt[1];
	GLfloat jx = cx + (2 * zoom / screen_w) * dx;
	GLfloat jy = cy + (2 * zoom / screen_h) * dy;
	// backwards, yech
    	//glUniform2f( julia_c_pos, jx, jy );
    	glUniform2f( julia_c_pos, jy, jx );
	glutPostRedisplay();
    }
}

static void mouse( int button, int state, int x, int y )
{
    switch (button)
    {
    case GLUT_LEFT_BUTTON:
    	bDragging = (state == GLUT_DOWN);
	nDragPt[0] = x;
	nDragPt[1] = y;
	if (bDragging) glutPostRedisplay();
    	break;

    case GLUT_RIGHT_BUTTON:
	if (state == GLUT_DOWN)
	{
    	    bJuliaing = true;
    	    glUseProgram( hJuliaProg );
	    // first point is at current center
    	    nJuliaPt[0] = screen_w / 2;
    	    nJuliaPt[1] = screen_h / 2;
	}
    	else if (state != GLUT_DOWN)
	{
    	    bJuliaing = false;
    	    glUseProgram( hMandProg );
	}
	glutPostRedisplay();
	break;

    case 3:
    	if (state == GLUT_DOWN)
	{
	    zoom *= 0.9;
	    if (zoom < 1e-9) zoom = 1e-9;
	    glutPostRedisplay();
	}
	break;

    case 4:
    	if (state == GLUT_DOWN)
	{
	    zoom *= 1.1;
	    if (zoom > 2) zoom = 2;
	    glutPostRedisplay();
	}
	break;

    default:
    	printf( "button %d %s
", button, (state == GLUT_DOWN) ? "down" : "up" );
    	break;
    }
}

static void keyboard( unsigned char c, int x, int y )
{
    switch (c)
    {
    case 27:
	exit( 0 );
	break;
    }
}

int main( int argc, char *argv[] )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );
    glutInitWindowSize( SCREEN_W, SCREEN_H );
    glutCreateWindow( "GL 2.0 test" );
    glutReshapeFunc( reshape );
    glutDisplayFunc( display );
    glutKeyboardFunc( keyboard );
    glutMouseFunc( mouse );
    glutMotionFunc( motion );

    init();

    glutMainLoop();

    return( 0 );
}


The Makefile that works for me under Linux:

all: psmand

%: %.cpp
        g++ -o $@ $< -L/usr/X11R6/lib -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm

another question:
i have download gll source code. it includes a *.vert and *.frag file.

http://developer.3dlabs.com/downloads/glsldemo/

is it possible to run this files without the GLSLdemo Windows installer?

can someone create me a visual studio project file for this?

pleease i need it so badly.
thx

May I ask you what and why are you actually studying? :-/

Originally posted by gigadude:
Much text

Thanks für that code, unfortunately I can not get it to work under Windows with MS Visual Studio 2003.
We (web and me) learned just Java in university and now we have to program a GPU so we have to get familiar with C/C++/Cg and MS Visual Studio as quickly as possible. Can you please point me how I can get that code compiled? Thanks in advance :slight_smile:
Oh I forgot about the errors, could be useful :wink:
I included the line “#include <windows.h>” on top of the file and during linking I get the following error messages:
“Nicht aufgelöstes externes Symbol” is german for “Nonresolved external symbol” (I hope I got that right :wink: )

@Brian Paul:
thanlk but have u any idea how can i get the extfuncs.h?
:wink:

You can find the extension registry and links to the headers here (glext.h and so forth):
http://www.opengl.org/registry/

Cheers

yes but not this one…or?

I’m sorry, but I don’t understand what you’re asking.

If you’re confused about how to load extensions, you might want to look at one of the extension loaders (glew/glee), which you can read about in the sticky wiki.

Cheers

Reedbeta has a mandelbrot (opengl) avaiable for download WITH source-code.

http://pages.pomona.edu/~nrr02004/opengl.html