//Vertex Program to set vertex position and texture coordinates struct v_Output { float4 position : POSITION; float2 texCoord2d : TEXCOORD0; }; v_Output vertexShader(float2 position : POSITION, float2 texCoord : TEXCOORD0) { v_Output OUT; OUT.position = float4(position,0,1); OUT.texCoord2d = texCoord; return OUT; } //Fragment shader to write color for each pixel uniform sampler2D permTexture; #define ONE 0.00390625 #define ONEHALF 0.001953125 varying float3 v_texCoord3D; float fade(float t) { //return t*t*(3.0-2.0*t); // Old fade return t*t*t*(t*(t*6.0-15.0)+10.0); // Improved fade } float noise(float3 P) { float3 Pi = ONE*floor(P)+ONEHALF; float3 Pf = P-floor(P); // Noise contributions from (x=0, y=0), z=0 and z=1 float perm00 = tex2D(permTexture, Pi.xy).a ; float3 grad000 = tex2D(permTexture, float2(perm00, Pi.z)).rgb * 4.0 - 1.0; float n000 = dot(grad000, Pf); float3 grad001 = tex2D(permTexture, float2(perm00, Pi.z + ONE)).rgb * 4.0 - 1.0; float n001 = dot(grad001, Pf - float3(0.0, 0.0, 1.0)); // Noise contributions from (x=0, y=1), z=0 and z=1 float perm01 = tex2D(permTexture, Pi.xy + float2(0.0, ONE)).a ; float3 grad010 = tex2D(permTexture, float2(perm01, Pi.z)).rgb * 4.0 - 1.0; float n010 = dot(grad010, Pf - float3(0.0, 1.0, 0.0)); float3 grad011 = tex2D(permTexture, float2(perm01, Pi.z + ONE)).rgb * 4.0 - 1.0; float n011 = dot(grad011, Pf - float3(0.0, 1.0, 1.0)); // Noise contributions from (x=1, y=0), z=0 and z=1 float perm10 = tex2D(permTexture, Pi.xy + float2(ONE, 0.0)).a ; float3 grad100 = tex2D(permTexture, float2(perm10, Pi.z)).rgb * 4.0 - 1.0; float n100 = dot(grad100, Pf - float3(1.0, 0.0, 0.0)); float3 grad101 = tex2D(permTexture, float2(perm10, Pi.z + ONE)).rgb * 4.0 - 1.0; float n101 = dot(grad101, Pf - float3(1.0, 0.0, 1.0)); // Noise contributions from (x=1, y=1), z=0 and z=1 float perm11 = tex2D(permTexture, Pi.xy + float2(ONE, ONE)).a ; float3 grad110 = tex2D(permTexture, float2(perm11, Pi.z)).rgb * 4.0 - 1.0; float n110 = dot(grad110, Pf - float3(1.0, 1.0, 0.0)); float3 grad111 = tex2D(permTexture, float2(perm11, Pi.z + ONE)).rgb * 4.0 - 1.0; float n111 = dot(grad111, Pf - float3(1.0, 1.0, 1.0)); // Blend contributions along x float4 n_x = lerp(float4(n000, n001, n010, n011), float4(n100, n101, n110, n111), fade(Pf.x)); // Blend contributions along y float2 n_xy = lerp(n_x.xy, n_x.zw, fade(Pf.y)); // Blend contributions along z float n_xyz = lerp(n_xy.x, n_xy.y, fade(Pf.z)); return n_xyz; } float turbulence(int octaves, float3 P, float lacunarity, float gain) { float sum = 0; float scale = 1; float totalgain = 1; for(int i=0;i #include #include #if __APPLE__ #include #else #include #endif #include #include #include #define M_PI 3.14159265358979323846 static CGcontext myCgContext; static CGprofile myCgVertexProfile, myCgFragmentProfile; static CGprogram myCgVertexProgram, myCgFragmentProgram; static const char *myProgramName = "mainProgram", *myVertexProgramFileName = "vertexShader.cg", *myVertexProgramName = "vertexShader", *myFragmentProgramFileName = "fragmentShader.cg", *myFragmentProgramName = "fragmentShader"; int perm[256]= {151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}; int grad3[16][3] = {{0,1,1},{0,1,-1},{0,-1,1},{0,-1,-1}, {1,0,1},{1,0,-1},{-1,0,1},{-1,0,-1}, {1,1,0},{1,-1,0},{-1,1,0},{-1,-1,0}, // 12 cube edges {1,0,-1},{-1,0,-1},{0,-1,1},{0,1,1}}; // 4 more to make 16 GLuint permTextureID; void initPermTexture(GLuint *texID) { char *pixels; int i,j; glGenTextures(1, texID); // Generate a unique texture ID glBindTexture(GL_TEXTURE_2D, *texID); // Bind the texture to texture unit 0 pixels = (char*)malloc( 256*256*4 ); for(i = 0; i<256; i++) for(j = 0; j<256; j++) { int offset = (i*256+j)*4; char value = perm[(j+perm[i]) & 0xFF]; pixels[offset] = grad3[value & 0x0F][0] * 64 + 64; // Gradient x pixels[offset+1] = grad3[value & 0x0F][1] * 64 + 64; // Gradient y pixels[offset+2] = grad3[value & 0x0F][2] * 64 + 64; // Gradient z pixels[offset+3] = value; // Permuted index } glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); } static void checkForCgError(const char *situation) { CGerror error; const char *string = cgGetLastErrorString(&error); if (error != CG_NO_ERROR) { printf("%s: %s: %s\n", myProgramName, situation, string); if (error == CG_COMPILER_ERROR) { printf("%s\n", cgGetLastListing(myCgContext)); } exit(1); } } /* Forward declared GLUT callbacks registered by main. */ static void display(void); static void keyboard(unsigned char c, int x, int y); int main(int argc, char **argv) { const GLubyte *image; unsigned int size, level; int width=600, height=600; glutInitWindowSize(600, 600); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInit(&argc, argv); glutCreateWindow("Perlin Noise Implementation on GPU"); glutDisplayFunc(display); glutKeyboardFunc(keyboard); glClearColor(0.1, 0.3, 0.6, 0.0); glEnable(GL_TEXTURE_1D); // Enable 1D texturing glEnable(GL_TEXTURE_2D); // Enable 2D texturing // Create and load the textures (generated, not read from a file) initPermTexture(&permTextureID); myCgContext = cgCreateContext(); checkForCgError("creating context"); myCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); cgGLSetOptimalOptions(myCgVertexProfile); checkForCgError("selecting vertex profile"); myCgVertexProgram = cgCreateProgramFromFile( myCgContext, /* Cg runtime context */ CG_SOURCE, /* Program in human-readable form */ myVertexProgramFileName, /* Name of file containing program */ myCgVertexProfile, /* Profile: OpenGL ARB vertex program */ myVertexProgramName, /* Entry function name */ NULL); /* No extra compiler options */ checkForCgError("creating vertex program from file"); cgGLLoadProgram(myCgVertexProgram); checkForCgError("loading vertex program"); /* No uniform vertex program parameters expected. */ myCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); cgGLSetOptimalOptions(myCgFragmentProfile); checkForCgError("selecting fragment profile"); myCgFragmentProgram = cgCreateProgramFromFile( myCgContext, /* Cg runtime context */ CG_SOURCE, /* Program in human-readable form */ myFragmentProgramFileName, /* Name of file containing program */ myCgFragmentProfile, /* Profile: OpenGL ARB vertex program */ myFragmentProgramName, /* Entry function name */ NULL); /* No extra compiler options */ checkForCgError("creating fragment program from file"); cgGLLoadProgram(myCgFragmentProgram); checkForCgError("loading fragment program"); glutMainLoop(); return 0; } static void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); cgGLBindProgram(myCgVertexProgram); checkForCgError("binding vertex program"); cgGLEnableProfile(myCgVertexProfile); checkForCgError("enabling vertex profile"); cgGLBindProgram(myCgFragmentProgram); checkForCgError("binding fragment program"); cgGLEnableProfile(myCgFragmentProfile); checkForCgError("enabling fragment profile"); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(-0.6, 0.6); glTexCoord2f(3, 0); glVertex2f(0.6, 0.6); glTexCoord2f(3, 3); glVertex2f(0.6, -0.6); glTexCoord2f(0, 3); glVertex2f(-0.6, -0.6); glEnd(); cgGLDisableProfile(myCgVertexProfile); checkForCgError("disabling vertex profile"); cgGLDisableProfile(myCgFragmentProfile); checkForCgError("disabling fragment profile"); glutSwapBuffers(); } static void keyboard(unsigned char c, int x, int y) { switch (c) { case 27: /* Esc key */ cgDestroyProgram(myCgVertexProgram); cgDestroyProgram(myCgFragmentProgram); cgDestroyContext(myCgContext); exit(0); break; } }