//---------------------------------------------------------------------------
// www.GPGPU.org
// Sample Code
//---------------------------------------------------------------------------
// Copyright (c) 2004 Mark J. Harris and GPGPU.org
// Copyright (c) 2004 3Dlabs Inc. Ltd.
//---------------------------------------------------------------------------
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any
// damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any
// purpose, including commercial applications, and to alter it and
// redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you
// must not claim that you wrote the original software. If you use
// this software in a product, an acknowledgment in the product
// documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and
// must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//---------------------------------------------------------------------------
// Author: Mark Harris (harrism@gpgpu.org) - original helloGPGPU
// Author: Mike Weiblen (mike.weiblen@3dlabs.com) - GLSL version
//---------------------------------------------------------------------------
// GPGPU Lesson 0: "helloGPGPU_GLSL" (a GLSL version of "helloGPGPU")
//---------------------------------------------------------------------------
//
// GPGPU CONCEPTS Introduced:
//
// 1.) Texture = Array
// 2.) Fragment Program = Computational Kernel.
// 3.) One-to-one Pixel to Texel Mapping:
// a) Data-Dimensioned Viewport, and
// b) Orthographic Projection.
// 4.) Viewport-Sized Quad = Data Stream Generator.
// 5.) Copy To Texture = feedback.
//
// For details of each of these concepts, see the explanations in the
// inline "GPGPU CONCEPT" comments in the code below.
//
// APPLICATION Demonstrated: A simple post-process edge detection filter.
//
//---------------------------------------------------------------------------
// Notes regarding this "helloGPGPU_GLSL" source code:
//
// This example was derived from the original "helloGPGPU.cpp" v1.0.1
// by Mark J. Harris. It demonstrates the same simple post-process edge
// detection filter, but instead implemented using the OpenGL Shading Language
// (also known as "GLSL"), an extension of the OpenGL v1.5 specification.
// Because the GLSL compiler is an integral part of a vendor's OpenGL driver,
// no additional GLSL development tools are required.
// This example was developed/tested on 3Dlabs Wildcat Realizm.
//
// I intentionally minimized changes to the structure of the original code
// to support a side-by-side comparison of the implementations.
//
// Thanks to Mark for making the original helloGPGPU example available!
//
// -- Mike Weiblen, May 2004
//
//
// [MJH:]
// This example has also been tested on NVIDIA GeForce FX and GeForce 6800 GPUs.
//
// Note that the example requires glew.h and glew32s.lib, available at
// http://glew.sourceforge.net.
//
// Thanks to Mike for modifying the example. I have actually changed my
// original code to match; for example the inline Cg code instead of an
// external file.
//
// -- Mark Harris, June 2004
//
// References:
// http://gpgpu.sourceforge.net/
// http://glew.sourceforge.net/
// http://www.xmission.com/~nate/glut.html
//---------------------------------------------------------------------------
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#define GLEW_STATIC 1
#include <GL/glew.h>
#include <GL/glut.h>
// forward declarations
class HelloGPGPU;
void reshape(int w, int h);
// globals
HelloGPGPU *g_pHello;
// This shader performs a 9-tap Laplacian edge detection filter.
// (converted from the separate "edges.cg" file to embedded GLSL string)
static const char *edgeFragSource = {
"uniform sampler2D texUnit;"
"void main(void)"
"{"
" const float offset = 1.0 / 512.0;"
" vec2 texCoord = gl_TexCoord[0].xy;"
" vec4 c = texture2D(texUnit, texCoord);"
" vec4 bl = texture2D(texUnit, texCoord + vec2(-offset, -offset));"
" vec4 l = texture2D(texUnit, texCoord + vec2(-offset, 0.0));"
" vec4 tl = texture2D(texUnit, texCoord + vec2(-offset, offset));"
" vec4 t = texture2D(texUnit, texCoord + vec2( 0.0, offset));"
" vec4 ur = texture2D(texUnit, texCoord + vec2( offset, offset));"
" vec4 r = texture2D(texUnit, texCoord + vec2( offset, 0.0));"
" vec4 br = texture2D(texUnit, texCoord + vec2( offset, -offset));"
" vec4 b = texture2D(texUnit, texCoord + vec2( 0.0, -offset));"
" gl_FragColor = 8.0 * (c + -0.125 * (bl + l + tl + t + ur + r + br + b));"
"}"
};
// This class encapsulates all of the GPGPU functionality of the example.
class HelloGPGPU
{
protected: // data
int _iWidth, _iHeight; // The dimensions of our array
float _rAngle; // used for animation
unsigned int _iTexture; // The texture used as a data array
GLhandleARB _programObject; // the program used to update
GLhandleARB _fragmentShader;
GLint _texUnit; // a parameter to the fragment program
public: // methods
HelloGPGPU(int w, int h)
: _rAngle(0),
_iWidth(w),
_iHeight(h)
{
// Create a simple 2D texture. This example does not use
// render to texture -- it just copies from the framebuffer to the
// texture.
// GPGPU CONCEPT 1: Texture = Array.
// Textures are the GPGPU equivalent of arrays in standard
// computation. Here we allocate a texture large enough to fit our
// data (which is arbitrary in this example).
glGenTextures(1, &_iTexture);
glBindTexture(GL_TEXTURE_2D, _iTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _iWidth, _iHeight,
0, GL_RGB, GL_FLOAT, 0);
// GPGPU CONCEPT 2: Fragment Program = Computational Kernel.
// A fragment program can be thought of as a small computational
// kernel that is applied in parallel to many fragments
// simultaneously. Here we load a kernel that performs an edge
// detection filter on an image.
_programObject = glCreateProgramObjectARB();
// Create the edge detection fragment program
_fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
glShaderSourceARB(_fragmentShader, 1, &edgeFragSource, NULL);
glCompileShaderARB(_fragmentShader);
glAttachObjectARB(_programObject, _fragmentShader);
// Link the shader into a complete GLSL program.
glLinkProgramARB(_programObject);
GLint progLinkSuccess;
glGetObjectParameterivARB(_programObject, GL_OBJECT_LINK_STATUS_ARB,
&progLinkSuccess);
if (!progLinkSuccess)
{
fprintf(stderr, "Filter shader could not be linked\n");
exit(1);
}
// Get location of the sampler uniform
_texUnit = glGetUniformLocationARB(_programObject, "texUnit");
}
~HelloGPGPU()
{
}
// This method updates the texture by rendering the ge
评论0