Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- //
- // Author: Joe Dobmeier
- // Credits: I created this program by combining the SimpleTexture2D
- // tutorial in the OpenGL ES 2.0 programming guide by
- // Munshi, Ginsburg, and Shreiner with legacy GPGPU
- // tutorial 0 from gpgpu.org by Harris and Weiblen.
- //
- //
- // 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.
- //
- // helloPiGPU_GLESSL.c
- //---------------------------------------------------------------------------
- // GPGPU Lesson 0: "helloPiGPU_GLESSL" (a GLESSL version of "helloGPGPU" for the RPi)
- //---------------------------------------------------------------------------
- //
- // 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.
- //
- //---------------------------------------------------------------------------
- //
- //
- #include <stdlib.h>
- #include "esUtil.h"
- typedef struct
- {
- // Handle to a program object
- GLuint programObject;
- // Attribute locations
- GLint positionLoc;
- GLint texCoordLoc;
- // Sampler location
- GLint samplerLoc;
- // Texture handle
- GLuint textureId;
- } UserData;
- ///
- // Create a simple 2x2 texture image with four different colors
- //
- // 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).
- GLuint CreateSimpleTexture2D( )
- {
- // Texture object handle
- GLuint textureId;
- // 2x2 Image, 3 bytes per pixel (R, G, B)
- GLubyte pixels[4 * 3] =
- {
- 255, 0, 0, // Red
- 0, 255, 0, // Green
- 0, 0, 255, // Blue
- 255, 255, 255 // White
- };
- // Use tightly packed data
- glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
- // Generate a texture object
- glGenTextures ( 1, &textureId );
- // Bind the texture object
- glBindTexture ( GL_TEXTURE_2D, textureId );
- // Load the texture
- glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
- // Set the filtering mode
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- return textureId;
- }
- ///
- // Initialize the shader and program object
- //
- // 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.
- int Init ( ESContext *esContext )
- {
- esContext->userData = malloc(sizeof(UserData));
- UserData *userData = esContext->userData;
- GLbyte vShaderStr[] =
- "attribute vec4 a_position; \n"
- "attribute vec2 a_texCoord; \n"
- "varying vec2 v_texCoord; \n"
- "void main() \n"
- "{ \n"
- " gl_Position = a_position; \n"
- " v_texCoord = a_texCoord; \n"
- "} \n";
- GLbyte fShaderStr[] =
- "precision mediump float; \n"
- "varying vec2 v_texCoord; \n"
- "uniform sampler2D s_texture; \n"
- "void main() \n"
- "{ \n"
- " const float offset = 1.0 / 256.0;\n"
- " vec4 c = texture2D(s_texture, v_texCoord);\n"
- " vec4 bl = texture2D(s_texture, v_texCoord + vec2(-offset, -offset));\n"
- " vec4 l = texture2D(s_texture, v_texCoord + vec2(-offset, 0.0));\n"
- " vec4 tl = texture2D(s_texture, v_texCoord + vec2(-offset, offset));\n"
- " vec4 t = texture2D(s_texture, v_texCoord + vec2( 0.0, offset));\n"
- " vec4 ur = texture2D(s_texture, v_texCoord + vec2( offset, offset));\n"
- " vec4 r = texture2D(s_texture, v_texCoord + vec2( offset, 0.0));\n"
- " vec4 br = texture2D(s_texture, v_texCoord + vec2( offset, offset));\n"
- " vec4 b = texture2D(s_texture, v_texCoord + vec2( 0.0, -offset));\n"
- " gl_FragColor = 8.0 * (c + -0.125 * (bl + l + tl + t + ur + r + br + b));\n"
- "} \n";
- // Load the shaders and get a linked program object
- userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
- // Get the attribute locations
- userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
- userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
- // Get the sampler location
- userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
- // Load the texture
- userData->textureId = CreateSimpleTexture2D ();
- glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
- return GL_TRUE;
- }
- ///
- // Draw a triangle using the shader pair created in Init()
- //
- void Draw ( ESContext *esContext )
- {
- // Set the viewport
- // GPGPU CONCEPT 3a: One-to-one Pixel to Texel Mapping: A Data-
- // Dimensioned Viewport.
- // We need a one-to-one mapping of pixels to texels in order to
- // ensure every element of our texture is processed. By setting our
- // viewport to the dimensions of our destination texture and drawing
- // a screen-sized quad (see below), we ensure that every pixel of our
- // texel is generated and processed in the fragment program.
- glViewport ( 0, 0, esContext->width, esContext->height );
- // GPGPU CONCEPT 4: Viewport-Sized Quad = Data Stream Generator.
- // In order to execute fragment programs, we need to generate pixels.
- // Drawing a quad the size of our viewport (see above) generates a
- // fragment for every pixel of our destination texture. Each fragment
- // is processed identically by the fragment program. Notice that in
- // the reshape() function, below, we have set the frustum to
- // orthographic, and the frustum dimensions to [-1,1]. Thus, our
- // viewport-sized quad vertices are at [-1,-1], [1,-1], [1,1], and
- // [-1,1]: the corners of the viewport.
- UserData *userData = esContext->userData;
- GLfloat vVertices[] = { -1.0f, 1.0f, 0.0f, // Position 0
- 0.0f, 0.0f, // TexCoord 0
- -1.0f, -1.0f, 0.0f, // Position 1
- 0.0f, 1.0f, // TexCoord 1
- 1.0f, -1.0f, 0.0f, // Position 2
- 1.0f, 1.0f, // TexCoord 2
- 1.0f, 1.0f, 0.0f, // Position 3
- 1.0f, 0.0f // TexCoord 3
- };
- GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
- // Clear the color buffer
- glClear ( GL_COLOR_BUFFER_BIT );
- // Use the program object
- glUseProgram ( userData->programObject );
- // Load the vertex position
- glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
- GL_FALSE, 5 * sizeof(GLfloat), vVertices );
- // Load the texture coordinate
- glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
- GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
- glEnableVertexAttribArray ( userData->positionLoc );
- glEnableVertexAttribArray ( userData->texCoordLoc );
- // Bind the texture
- glActiveTexture ( GL_TEXTURE0 );
- glBindTexture ( GL_TEXTURE_2D, userData->textureId );
- // Set the sampler texture unit to 0
- glUniform1i ( userData->samplerLoc, 0 );
- glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
- }
- ///
- // Cleanup
- //
- void ShutDown ( ESContext *esContext )
- {
- UserData *userData = esContext->userData;
- // Delete texture object
- glDeleteTextures ( 1, &userData->textureId );
- // Delete program object
- glDeleteProgram ( userData->programObject );
- free(esContext->userData);
- }
- int main ( int argc, char *argv[] )
- {
- ESContext esContext;
- UserData userData;
- esInitContext ( &esContext );
- esContext.userData = &userData;
- esCreateWindow ( &esContext, "helloPiGPU_GLESSL", 256, 256, ES_WINDOW_RGB );
- if ( !Init ( &esContext ) )
- return 0;
- esRegisterDrawFunc ( &esContext, Draw );
- esMainLoop ( &esContext );
- ShutDown ( &esContext );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement