noise.c
// |
// File: noise.c |
// |
// Abstract: This example shows how OpenCL can be used for procedural texture synthesis |
// and intermix with existing OpenGL textures for display. Several compute |
// kernels are provided which generate a variety of procedural functions, |
// including gradient noise (aka Perlin Noise), turbulence and other |
// fractals. |
// |
// Version: <1.0> |
// |
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") |
// in consideration of your agreement to the following terms, and your use, |
// installation, modification or redistribution of this Apple software |
// constitutes acceptance of these terms. If you do not agree with these |
// terms, please do not use, install, modify or redistribute this Apple |
// software. |
// |
// In consideration of your agreement to abide by the following terms, and |
// subject to these terms, Apple grants you a personal, non - exclusive |
// license, under Apple's copyrights in this original Apple software ( the |
// "Apple Software" ), to use, reproduce, modify and redistribute the Apple |
// Software, with or without modifications, in source and / or binary forms; |
// provided that if you redistribute the Apple Software in its entirety and |
// without modifications, you must retain this notice and the following text |
// and disclaimers in all such redistributions of the Apple Software. Neither |
// the name, trademarks, service marks or logos of Apple Inc. may be used to |
// endorse or promote products derived from the Apple Software without specific |
// prior written permission from Apple. Except as expressly stated in this |
// notice, no other rights or licenses, express or implied, are granted by |
// Apple herein, including but not limited to any patent rights that may be |
// infringed by your derivative works or by other works in which the Apple |
// Software may be incorporated. |
// |
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A |
// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION |
// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
// |
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION |
// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER |
// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR |
// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
// |
// Copyright ( C ) 2008 Apple Inc. All Rights Reserved. |
// |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
#include <fcntl.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <math.h> |
#include <unistd.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <OpenGL/OpenGL.h> |
#include <OpenCL/opencl.h> |
#include <GLUT/glut.h> |
#include <mach/mach_time.h> |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
#define USE_GL_ATTACHMENTS (1) // enable OpenGL attachments for Compute results |
#define DEBUG_INFO (0) // enable debug info |
#define SEPARATOR ("----------------------------------------------------------------------\n") |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
static cl_context ComputeContext; |
static cl_command_queue ComputeCommands; |
static cl_kernel ComputeKernel; |
static cl_program ComputeProgram; |
static cl_device_id ComputeDeviceId; |
static cl_device_type ComputeDeviceType; |
static cl_mem ComputeResult; |
#if USE_GL_ATTACHMENTS |
static cl_mem ComputeImage; |
#endif |
//////////////////////////////////////////////////////////////////////////////// |
#define COMPUTE_KERNEL_FILENAME ("noise_kernel.cl") |
#define COMPUTE_KERNEL_COUNT 4 |
static cl_kernel ComputeKernels[COMPUTE_KERNEL_COUNT]; |
static int ComputeKernelWorkGroupSizes[COMPUTE_KERNEL_COUNT]; |
static const char * ComputeKernelMethods[COMPUTE_KERNEL_COUNT] = |
{ |
"GradientNoiseArray2d", |
"MonoFractalArray2d", |
"TurbulenceArray2d", |
"RidgedMultiFractalArray2d", |
}; |
//////////////////////////////////////////////////////////////////////////////// |
static uint TextureId = 0; |
static uint TextureTarget = GL_TEXTURE_2D; |
static uint TextureInternal = GL_RGBA; |
static uint TextureFormat = GL_BGRA; |
static uint TextureType = GL_UNSIGNED_INT_8_8_8_8_REV; |
static size_t TextureTypeSize = sizeof(char); |
static uint ActiveTextureUnit = GL_TEXTURE1_ARB; |
static void* HostImageBuffer = 0; |
static int Width = 512; |
static int Height = 512; |
static float Scale = 20.0f; |
static float Bias[2] = { 128.0f, 128.0f }; |
static float Lacunarity = 2.02f; |
static float Increment = 1.0f; |
static float Octaves = 3.3f; |
static float Amplitude = 1.0f; |
static float ShadowTextColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; |
static float HighlightTextColor[4] = { 0.2f, 0.6f, 0.8f, 1.0f }; |
static uint TextOffset[2] = { 20, 20 }; |
static int MouseX = 0; |
static int MouseY = 0; |
static int ButtonState = 0; |
static int ActiveKernel = 0; |
static double TimeElapsed = 0; |
static int FrameCount = 0; |
static uint ReportStatsInterval = 60; |
static char StatsString[1024] = "\0"; |
static char InfoString[1024] = "\0"; |
static uint ShowInfo = 0; |
//////////////////////////////////////////////////////////////////////////////// |
static float TexCoords[4][2]; |
static float VertexPos[4][2] = |
{ |
{ -1.0f, -1.0f }, |
{ 1.0f, -1.0f }, |
{ 1.0f, 1.0f }, |
{ -1.0f, 1.0f } |
}; |
//////////////////////////////////////////////////////////////////////////////// |
static uint64_t |
GetCurrentTime() |
{ |
return mach_absolute_time(); |
} |
static double |
SubtractTime( uint64_t uiEndTime, uint64_t uiStartTime ) |
{ |
static double s_dConversion = 0.0; |
uint64_t uiDifference = uiEndTime - uiStartTime; |
if( 0 == s_dConversion ) |
{ |
mach_timebase_info_data_t kTimebase; |
kern_return_t kError = mach_timebase_info( &kTimebase ); |
if( kError == 0 ) |
s_dConversion = 1e-9 * (double) kTimebase.numer / (double) kTimebase.denom; |
} |
return s_dConversion * (double) uiDifference; |
} |
static int |
FloorPow2(int n) |
{ |
int exp; |
frexp((float)n, &exp); |
return 1 << (exp - 1); |
} |
//////////////////////////////////////////////////////////////////////////////// |
static int LoadTextFromFile( |
const char *file_name, char **result_string, size_t *string_len) |
{ |
int fd; |
unsigned file_len; |
struct stat file_status; |
int ret; |
*string_len = 0; |
fd = open(file_name, O_RDONLY); |
if (fd == -1) |
{ |
printf("Error opening file %s\n", file_name); |
return -1; |
} |
ret = fstat(fd, &file_status); |
if (ret) |
{ |
printf("Error reading status for file %s\n", file_name); |
return -1; |
} |
file_len = file_status.st_size; |
*result_string = (char*)calloc(file_len + 1, sizeof(char)); |
ret = read(fd, *result_string, file_len); |
if (!ret) |
{ |
printf("Error reading from file %s\n", file_name); |
return -1; |
} |
close(fd); |
*string_len = file_len; |
return 0; |
} |
static void |
CreateTexture(uint width, uint height) |
{ |
if (HostImageBuffer) |
free(HostImageBuffer); |
HostImageBuffer = malloc(Width * Height * TextureTypeSize * 4); |
memset(HostImageBuffer, 0, Width * Height * TextureTypeSize * 4); |
glActiveTextureARB(ActiveTextureUnit); |
glGenTextures(1, &TextureId); |
glBindTexture(TextureTarget, TextureId); |
glTexParameteri(TextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP); |
glTexParameteri(TextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP); |
glTexParameteri(TextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
glTexParameteri(TextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
glTexImage2D(TextureTarget, 0, TextureInternal, width, height, 0, |
TextureFormat, TextureType, HostImageBuffer); |
glBindTexture(TextureTarget, 0); |
#if USE_GL_ATTACHMENTS |
free(HostImageBuffer); |
HostImageBuffer = 0; |
#endif |
} |
static void |
RenderTexture( void *pvData ) |
{ |
glDisable( GL_LIGHTING ); |
glViewport( 0, 0, Width, Height ); |
glMatrixMode( GL_PROJECTION ); |
glLoadIdentity(); |
gluOrtho2D( -1.0, 1.0, -1.0, 1.0 ); |
glMatrixMode( GL_MODELVIEW ); |
glLoadIdentity(); |
glMatrixMode( GL_TEXTURE ); |
glLoadIdentity(); |
glEnable( TextureTarget ); |
glBindTexture( TextureTarget, TextureId ); |
if(pvData) |
glTexSubImage2D(TextureTarget, 0, 0, 0, Width, Height, |
TextureFormat, TextureType, pvData); |
glTexParameteri(TextureTarget, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); |
glBegin( GL_QUADS ); |
{ |
glColor3f(1.0f, 1.0f, 1.0f); |
glTexCoord2f( 0.0f, 0.0f ); |
glVertex3f( -1.0f, -1.0f, 0.0f ); |
glTexCoord2f( 0.0f, 1.0f ); |
glVertex3f( -1.0f, 1.0f, 0.0f ); |
glTexCoord2f( 1.0f, 1.0f ); |
glVertex3f( 1.0f, 1.0f, 0.0f ); |
glTexCoord2f( 1.0f, 0.0f ); |
glVertex3f( 1.0f, -1.0f, 0.0f ); |
} |
glEnd(); |
glBindTexture( TextureTarget, 0 ); |
glDisable( TextureTarget ); |
} |
static int |
Recompute(void) |
{ |
void *values[10]; |
size_t sizes[10]; |
size_t global[2]; |
size_t local[2]; |
int arg = 0; |
int err = 0; |
float bias[2] = { fabs(Bias[0]), fabs(Bias[1]) }; |
float scale[2] = { fabs(Scale), fabs(Scale) }; |
unsigned int v = 0, s = 0; |
values[v++] = &ComputeResult; |
values[v++] = bias; |
values[v++] = scale; |
if(ActiveKernel > 0) |
{ |
values[v++] = &Lacunarity; |
values[v++] = &Increment; |
values[v++] = &Octaves; |
} |
values[v++] = &Amplitude; |
sizes[s++] = sizeof(cl_mem); |
sizes[s++] = sizeof(float) * 2; |
sizes[s++] = sizeof(float) * 2; |
if(ActiveKernel > 0) |
{ |
sizes[s++] = sizeof(float); |
sizes[s++] = sizeof(float); |
sizes[s++] = sizeof(float); |
} |
sizes[s++] = sizeof(float); |
err = CL_SUCCESS; |
for (arg = 0; arg < s; arg++) |
{ |
err |= clSetKernelArg(ComputeKernels[ActiveKernel], arg, sizes[arg], values[arg]); |
} |
if (err) |
return -10; |
global[0] = Width; |
global[1] = Height; |
local[0] = ComputeKernelWorkGroupSizes[ActiveKernel]; |
local[1] = 1; |
#if DEBUG_INFO |
if(FrameCount <= 1) |
printf("Global[%4d %4d] Local[%4d %4d]\n", |
(int)global[0], (int)global[1], |
(int)local[0], (int)local[1]); |
#endif |
err = clEnqueueNDRangeKernel(ComputeCommands, ComputeKernels[ActiveKernel], 2, NULL, global, local, 0, NULL, NULL); |
if (err != CL_SUCCESS) |
{ |
printf("Failed to enqueue kernel! %d\n", err); |
return EXIT_FAILURE; |
} |
#if USE_GL_ATTACHMENTS |
err = clEnqueueAcquireGLObjects(ComputeCommands, 1, &ComputeImage, 0, 0, 0); |
if (err != CL_SUCCESS) |
{ |
printf("Failed to acquire GL object! %d\n", err); |
return EXIT_FAILURE; |
} |
size_t origin[] = { 0, 0, 0 }; |
size_t region[] = { Width, Height, 1 }; |
err = clEnqueueCopyBufferToImage(ComputeCommands, ComputeResult, ComputeImage, |
0, origin, region, 0, NULL, 0); |
if(err != CL_SUCCESS) |
{ |
printf("Failed to copy buffer to image! %d\n", err); |
return EXIT_FAILURE; |
} |
err = clEnqueueReleaseGLObjects(ComputeCommands, 1, &ComputeImage, 0, 0, 0); |
if (err != CL_SUCCESS) |
{ |
printf("Failed to release GL object! %d\n", err); |
return EXIT_FAILURE; |
} |
#else |
err = clEnqueueReadBuffer( ComputeCommands, ComputeResult, CL_TRUE, 0, |
Width * Height * TextureTypeSize * 4, |
HostImageBuffer, 0, NULL, NULL ); |
if (err) |
return -5; |
#endif |
return CL_SUCCESS; |
} |
//////////////////////////////////////////////////////////////////////////////// |
static int |
CreateComputeResult(void) |
{ |
int err = 0; |
printf(SEPARATOR); |
#if USE_GL_ATTACHMENTS |
printf("Allocating compute result image...\n"); |
ComputeImage = clCreateFromGLTexture2D(ComputeContext, CL_MEM_WRITE_ONLY, TextureTarget, 0, TextureId, &err); |
if (!ComputeImage || err != CL_SUCCESS) |
{ |
printf("Failed to create OpenGL texture reference! %d\n", err); |
return -1; |
} |
#endif |
printf("Allocating compute result buffer...\n"); |
ComputeResult = clCreateBuffer(ComputeContext, CL_MEM_WRITE_ONLY, TextureTypeSize * 4 * Width * Height, NULL, &err); |
if (!ComputeResult || err != CL_SUCCESS) |
{ |
printf("Failed to create OpenCL array! %d\n", err); |
return EXIT_FAILURE; |
} |
return CL_SUCCESS; |
} |
static int |
SetupComputeKernels(void) |
{ |
int err = 0; |
char *source = 0; |
size_t length = 0; |
printf(SEPARATOR); |
printf("Loading kernel source from file '%s'...\n", COMPUTE_KERNEL_FILENAME); |
err = LoadTextFromFile(COMPUTE_KERNEL_FILENAME, &source, &length); |
if (err) |
return -8; |
// Create the compute program from the source buffer |
// |
ComputeProgram = clCreateProgramWithSource(ComputeContext, 1, (const char **) & source, NULL, &err); |
if (!ComputeProgram || err != CL_SUCCESS) |
{ |
printf("Error: Failed to create compute program! %d\n", err); |
return EXIT_FAILURE; |
} |
// Build the program executable |
// |
printf(SEPARATOR); |
printf("Building compute program...\n"); |
err = clBuildProgram(ComputeProgram, 0, NULL, NULL, NULL, NULL); |
if (err != CL_SUCCESS) |
{ |
size_t len; |
char buffer[2048]; |
printf("Error: Failed to build program executable!\n"); |
clGetProgramBuildInfo(ComputeProgram, ComputeDeviceId, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len); |
printf("%s\n", buffer); |
return EXIT_FAILURE; |
} |
// Create the compute kernel from within the program |
// |
int i = 0; |
for(i = 0; i < COMPUTE_KERNEL_COUNT; i++) |
{ |
printf("Creating kernel '%s'...\n", ComputeKernelMethods[i]); |
ComputeKernels[i] = clCreateKernel(ComputeProgram, ComputeKernelMethods[i], &err); |
if (!ComputeKernels[i] || err != CL_SUCCESS) |
{ |
printf("Error: Failed to create compute kernel!\n"); |
return EXIT_FAILURE; |
} |
// Get the maximum work group size for executing the kernel on the device |
// |
size_t max = 1; |
err = clGetKernelWorkGroupInfo(ComputeKernels[i], ComputeDeviceId, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max, NULL); |
if (err != CL_SUCCESS) |
{ |
printf("Error: Failed to retrieve kernel work group info! %d\n", err); |
return EXIT_FAILURE; |
} |
ComputeKernelWorkGroupSizes[i] = (max > 1) ? FloorPow2(max) : max; // use nearest power of two (less than max) |
printf("%s MaxWorkGroupSize: %d\n", ComputeKernelMethods[i], (int)ComputeKernelWorkGroupSizes[i]); |
} |
return CreateComputeResult(); |
} |
static int |
SetupComputeDevices(int gpu) |
{ |
int err; |
size_t returned_size; |
ComputeDeviceType = gpu ? CL_DEVICE_TYPE_GPU : CL_DEVICE_TYPE_CPU; |
#if (USE_GL_ATTACHMENTS) |
printf(SEPARATOR); |
printf("Using active OpenGL context...\n"); |
CGLContextObj kCGLContext = CGLGetCurrentContext(); |
CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext); |
cl_context_properties properties[] = { |
CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, |
(cl_context_properties)kCGLShareGroup, 0 |
}; |
// Create a context from a CGL share group |
// |
ComputeContext = clCreateContext(properties, 0, 0, clLogMessagesToStdoutAPPLE, 0, 0); |
if (!ComputeContext) |
{ |
printf("Error: Failed to create a compute context!\n"); |
return EXIT_FAILURE; |
} |
#else |
// Locate a compute device |
// |
err = clGetDeviceIDs(NULL, ComputeDeviceType, 1, &ComputeDeviceId, NULL); |
if (err != CL_SUCCESS) |
{ |
printf("Error: Failed to locate compute device!\n"); |
return EXIT_FAILURE; |
} |
// Create a context containing the compute device(s) |
// |
ComputeContext = clCreateContext(0, 1, &ComputeDeviceId, clLogMessagesToStdoutAPPLE, NULL, &err); |
if (!ComputeContext) |
{ |
printf("Error: Failed to create a compute context!\n"); |
return EXIT_FAILURE; |
} |
#endif |
unsigned int device_count; |
cl_device_id device_ids[16]; |
err = clGetContextInfo(ComputeContext, CL_CONTEXT_DEVICES, sizeof(device_ids), device_ids, &returned_size); |
if(err) |
{ |
printf("Error: Failed to retrieve compute devices for context!\n"); |
return EXIT_FAILURE; |
} |
device_count = returned_size / sizeof(cl_device_id); |
int i = 0; |
int device_found = 0; |
cl_device_type device_type; |
for(i = 0; i < device_count; i++) |
{ |
clGetDeviceInfo(device_ids[i], CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, NULL); |
if(device_type == ComputeDeviceType) |
{ |
ComputeDeviceId = device_ids[i]; |
device_found = 1; |
break; |
} |
} |
if(!device_found) |
{ |
printf("Error: Failed to locate compute device!\n"); |
return EXIT_FAILURE; |
} |
// Create a command queue |
// |
ComputeCommands = clCreateCommandQueue(ComputeContext, ComputeDeviceId, 0, &err); |
if (!ComputeCommands) |
{ |
printf("Error: Failed to create a command queue!\n"); |
return EXIT_FAILURE; |
} |
// Report the device vendor and device name |
// |
cl_char vendor_name[1024] = {0}; |
cl_char device_name[1024] = {0}; |
err = clGetDeviceInfo(ComputeDeviceId, CL_DEVICE_VENDOR, sizeof(vendor_name), vendor_name, &returned_size); |
err|= clGetDeviceInfo(ComputeDeviceId, CL_DEVICE_NAME, sizeof(device_name), device_name, &returned_size); |
if (err != CL_SUCCESS) |
{ |
printf("Error: Failed to retrieve device info!\n"); |
return EXIT_FAILURE; |
} |
printf(SEPARATOR); |
printf("Connecting to %s %s...\n", vendor_name, device_name); |
return CL_SUCCESS; |
} |
static void |
ShutdownCompute(void) |
{ |
printf(SEPARATOR); |
printf("Shutting down...\n"); |
clFinish(ComputeCommands); |
clReleaseKernel(ComputeKernel); |
clReleaseProgram(ComputeProgram); |
clReleaseCommandQueue(ComputeCommands); |
clReleaseMemObject(ComputeResult); |
#if USE_GL_ATTACHMENTS |
clReleaseMemObject(ComputeImage); |
#endif |
} |
//////////////////////////////////////////////////////////////////////////////// |
static int |
SetupGraphics(void) |
{ |
glClearColor (0.0f, 0.0f, 0.0f, 0.0f); |
CreateTexture(Width, Height); |
glDisable(GL_DEPTH_TEST); |
glActiveTexture(GL_TEXTURE0); |
glViewport(0, 0, Width, Height); |
glMatrixMode(GL_MODELVIEW); |
glLoadIdentity(); |
glMatrixMode(GL_PROJECTION); |
glLoadIdentity(); |
TexCoords[3][0] = 0.0f; |
TexCoords[3][1] = 0.0f; |
TexCoords[2][0] = Width; |
TexCoords[2][1] = 0.0f; |
TexCoords[1][0] = Width; |
TexCoords[1][1] = Height; |
TexCoords[0][0] = 0.0f; |
TexCoords[0][1] = Height; |
glEnableClientState(GL_VERTEX_ARRAY); |
glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
glVertexPointer(2, GL_FLOAT, 0, VertexPos); |
glClientActiveTexture(GL_TEXTURE0); |
glTexCoordPointer(2, GL_FLOAT, 0, TexCoords); |
return GL_NO_ERROR; |
} |
static int |
Initialize(int gpu) |
{ |
int err; |
err = SetupGraphics(); |
if (err != GL_NO_ERROR) |
{ |
printf ("Failed to setup OpenGL state!"); |
exit (err); |
} |
err = SetupComputeDevices(gpu); |
if(err != CL_SUCCESS) |
{ |
printf ("Failed to connect to compute device! Error %d\n", err); |
exit (err); |
} |
err = SetupComputeKernels(); |
if (err != CL_SUCCESS) |
{ |
printf ("Failed to setup compute kernel! Error %d\n", err); |
exit (err); |
} |
printf(SEPARATOR); |
printf("Starting event loop...\n"); |
return CL_SUCCESS; |
} |
static void |
DrawString(float x, float y, float color[4], char *buffer) |
{ |
unsigned int uiLen, i; |
glRasterPos2f(x, y); |
glColor3f(color[0], color[1], color[2]); |
uiLen = (unsigned int) strlen(buffer); |
for (i = 0; i < uiLen; i++) |
{ |
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, buffer[i]); |
} |
} |
static void |
DrawText(float x, float y, float color[4], char *acString) |
{ |
GLint iVP[4]; |
GLint iMatrixMode; |
glColor3f(color[0], color[1], color[2]); |
glDisable(GL_DEPTH_TEST); |
glPushAttrib(GL_LIGHTING_BIT); |
glDisable(GL_LIGHTING); |
glGetIntegerv(GL_VIEWPORT, iVP); |
glViewport(0, 0, Width, Height); |
glGetIntegerv(GL_MATRIX_MODE, &iMatrixMode); |
glMatrixMode(GL_PROJECTION); |
glPushMatrix(); |
glLoadIdentity(); |
glMatrixMode(GL_MODELVIEW); |
glPushMatrix(); |
glLoadIdentity(); |
glScalef(2.0f / (float)Width, -2.0f / (float)Height, 1.0f); |
glTranslatef(-(float)Width / 2.0f, -(float)Height / 2.0f, 0.0f); |
DrawString(x, y, color, acString); |
glPopMatrix(); |
glMatrixMode(GL_PROJECTION); |
glPopMatrix(); |
glMatrixMode(iMatrixMode); |
glPopAttrib(); |
glViewport(iVP[0], iVP[1], iVP[2], iVP[3]); |
} |
static void |
ReportStats( |
uint64_t uiStartTime, uint64_t uiEndTime) |
{ |
TimeElapsed += SubtractTime(uiEndTime, uiStartTime); |
if(TimeElapsed && FrameCount && FrameCount > ReportStatsInterval) |
{ |
double fMs = (TimeElapsed * 1000.0 / (double) FrameCount); |
double fFps = 1.0 / (fMs / 1000.0); |
sprintf(StatsString, "[%s] Compute: %3.2f ms Display: %3.2f fps (%s)\n", |
(ComputeDeviceType == CL_DEVICE_TYPE_GPU) ? "GPU" : "CPU", |
fMs, fFps, USE_GL_ATTACHMENTS ? "attached" : "copying"); |
glutSetWindowTitle(StatsString); |
FrameCount = 0; |
TimeElapsed = 0; |
} |
} |
static void |
ReportInfo(void) |
{ |
if(ShowInfo == 0) |
return; |
int iX = TextOffset[0]; |
int iY = TextOffset[1]; |
DrawText(Width - iX - 1 - strlen(InfoString) * 10, Height - iY - 1, ShadowTextColor, InfoString); |
DrawText(Width - iX - 2 - strlen(InfoString) * 10, Height - iY - 2, ShadowTextColor, InfoString); |
DrawText(Width - iX - strlen(InfoString) * 10, Height - iY, HighlightTextColor, InfoString); |
ShowInfo = (ShowInfo > 200) ? 0 : ShowInfo + 1; |
} |
static void |
Display(void) |
{ |
FrameCount++; |
uint64_t uiStartTime = GetCurrentTime(); |
glClear (GL_COLOR_BUFFER_BIT); |
int err = Recompute(); |
if (err != 0) |
{ |
printf("Error %d from Recompute!\n", err); |
exit(1); |
} |
RenderTexture(HostImageBuffer); |
ReportInfo(); |
glFinish(); // for timing |
uint64_t uiEndTime = GetCurrentTime(); |
ReportStats(uiStartTime, uiEndTime); |
glutSwapBuffers(); |
glutPostRedisplay(); |
} |
static void |
Reshape (int w, int h) |
{ |
glViewport(0, 0, w, h); |
glMatrixMode(GL_MODELVIEW); |
glLoadIdentity(); |
glMatrixMode(GL_PROJECTION); |
glLoadIdentity(); |
} |
static void |
Keyboard(unsigned char key, int x, int y) |
{ |
switch (key) |
{ |
case '1': |
case '2': |
case '3': |
case '4': |
ActiveKernel = key - '1'; |
sprintf(InfoString, "%s\n", ComputeKernelMethods[ActiveKernel]); |
ShowInfo = 1; |
break; |
case '=': |
Scale *= 0.90; |
sprintf(InfoString,"Scale = %f\n", Scale); |
ShowInfo = 1; |
break; |
case '-': |
Scale *= 1.10; |
sprintf(InfoString,"Scale = %f\n", Scale); |
ShowInfo = 1; |
break; |
case 'q': |
exit(0); |
break; |
case 'z': |
Amplitude *= (1.0f / 1.1f); |
Amplitude = Amplitude < 0.0001f ? 0.0001f : Amplitude; |
sprintf(InfoString,"Amplitude = %f\n", Amplitude); |
ShowInfo = 1; |
break; |
case 'x': |
Amplitude *= (1.1f); |
sprintf(InfoString,"Amplitude = %f\n", Amplitude); |
ShowInfo = 1; |
break; |
case 'c': |
Octaves *= (1.0f / 1.1f); |
Octaves = Octaves < 1.0f ? 1.0f : Octaves; |
sprintf(InfoString,"Octaves = %f\n", Octaves); |
ShowInfo = 1; |
break; |
case 'v': |
Octaves *= (1.1f); |
Octaves = Octaves > 10.0f ? 10.0f : Octaves; |
sprintf(InfoString,"Octaves = %f\n", Octaves); |
ShowInfo = 1; |
break; |
case 'b': |
Lacunarity *= (1.0f / 1.0001f); |
printf("Lacunarity = %f\n", Lacunarity); |
sprintf(InfoString,"Lacunarity = %f\n", Lacunarity); |
ShowInfo = 1; |
break; |
case 'n': |
Lacunarity *= (1.0001f); |
sprintf(InfoString,"Lacunarity = %f\n", Lacunarity); |
ShowInfo = 1; |
break; |
case 'm': |
Increment *= (1.0f / 1.1f); |
sprintf(InfoString, "Increment = %f\n", Increment); |
ShowInfo = 1; |
break; |
case ',': |
Increment *= (1.1f); |
sprintf(InfoString, "Increment = %f\n", Increment); |
ShowInfo = 1; |
break; |
case 27: |
ShutdownCompute(); |
exit(0); |
break; |
} |
glutPostRedisplay(); |
} |
static void |
Motion(int x, int y) |
{ |
float dx, dy; |
dx = x - MouseX; |
dy = y - MouseY; |
if (ButtonState == 3) |
{ |
Scale += (dy / 100.0) * 0.5 * fabs(Scale); |
sprintf(InfoString,"Scale = %.3f\n", Scale); |
ShowInfo = 1; |
} |
else if (ButtonState & 1) |
{ |
Bias[0] += dx / 100.0f / Scale; |
Bias[1] += dy / 100.0f / Scale; |
sprintf(InfoString,"Bias = (%.3f, %.3f)\n", Bias[0], Bias[1]); |
ShowInfo = 1; |
} |
else if (ButtonState & 2) |
{ |
Bias[0] += dy / 5.0; |
Bias[1] += dx / 5.0; |
sprintf(InfoString,"Bias = (%.3f, %.3f)\n", Bias[0], Bias[1]); |
ShowInfo = 1; |
} |
MouseX = x; MouseY = y; |
glutPostRedisplay(); |
} |
static void |
Mouse(int button, int state, int x, int y) |
{ |
int mods; |
if (state == GLUT_DOWN) |
ButtonState |= 1<<button; |
else if (state == GLUT_UP) |
ButtonState = 0; |
mods = glutGetModifiers(); |
if (mods & GLUT_ACTIVE_SHIFT) |
{ |
ButtonState = 2; |
} |
else if (mods & GLUT_ACTIVE_CTRL) |
{ |
ButtonState = 3; |
} |
MouseX = x; MouseY = y; |
glutPostRedisplay(); |
} |
int main(int argc, char** argv) |
{ |
int use_gpu = 1; |
// Parse command line options |
// |
int i; |
for( i = 0; i < argc && argv; i++) |
{ |
if(!argv[i]) |
continue; |
if(strstr(argv[i], "cpu")) |
{ |
use_gpu = 0; |
} |
else if(strstr(argv[i], "gpu")) |
{ |
use_gpu = 1; |
} |
} |
glutInit(&argc, argv); |
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); |
glutInitWindowSize (Width, Height); |
glutInitWindowPosition (0, 0); |
glutCreateWindow (argv[0]); |
if (Initialize(use_gpu) == GL_NO_ERROR) |
{ |
glutDisplayFunc(Display); |
glutIdleFunc(Display); |
glutReshapeFunc(Reshape); |
glutKeyboardFunc(Keyboard); |
glutMouseFunc(Mouse); |
glutMotionFunc(Motion); |
glutMainLoop(); |
} |
atexit(ShutdownCompute); |
return 0; |
} |
Copyright © 2009 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2009-10-09