📄 imageprocessing.c
字号:
// ImageProcessing.c
// OpenGL SuperBible, Chapter 23
// Demonstrates convolution via fragment shaders
// Program by Benjamin Lipchak
#include "../../Common/OpenGLSB.h" // System and OpenGL Stuff
#include "../../Common/GLTools.h" // System and OpenGL Stuff
#include <stdio.h>
#ifndef __APPLE__
PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
PFNGLBINDPROGRAMARBPROC glBindProgramARB;
PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
#endif
PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
PFNGLGETHANDLEARBPROC glGetHandleARB;
PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
PFNGLUNIFORM1FARBPROC glUniform1fARB;
PFNGLUNIFORM1IARBPROC glUniform1iARB;
PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
#ifndef __APPLE__
PFNGLACTIVETEXTUREPROC glActiveTexture;
PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2f;
#endif
GLboolean lowLevelAvailable = GL_FALSE;
GLboolean highLevelAvailable = GL_FALSE;
GLboolean useHighLevel = GL_FALSE;
#define PASS_THROUGH 0
#define BLUR 1
#define SHARPEN 2
#define DILATION 3
#define EROSION 4
#define LAPLACIAN 5
#define SOBEL 6
#define PREWITT 7
#define TOTAL_SHADERS 8
GLuint ids[TOTAL_SHADERS]; // low-level shader object names
GLhandleARB fShader[TOTAL_SHADERS], progObj[TOTAL_SHADERS]; // high-level shader object handles
GLboolean needsValidation[TOTAL_SHADERS];
char *shaderNames[TOTAL_SHADERS] = {"passthrough", "blur", "sharpen", "dilation", "erosion",
"laplacian", "sobel", "prewitt"};
GLint whichShader = PASS_THROUGH; // current shader
GLint windowWidth = 512; // window size
GLint windowHeight = 512;
GLint textureWidth = 512; // texture size
GLint textureHeight = 512;
GLint mainMenu, shaderMenu, passMenu; // menu handles
GLint maxTexSize; // maximum allowed size for 1D/2D texture
GLfloat cameraPos[] = { 100.0f, 75.0f, 150.0f, 1.0f};
GLfloat lightPos[] = { 140.0f, 250.0f, 140.0f, 1.0f};
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f};
GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f};
GLfloat lightRotation = 0.0f;
GLfloat texCoordOffsets[18];
GLint numPasses = 2;
#define MAX_INFO_LOG_SIZE 2048
// Load shader from disk into a null-terminated string
GLubyte *LoadShaderText(const char *fileName)
{
GLubyte *shaderText = NULL;
GLint shaderLength = 0;
FILE *fp;
fp = fopen(fileName, "r");
if (fp != NULL)
{
while (fgetc(fp) != EOF)
{
shaderLength++;
}
rewind(fp);
shaderText = (GLubyte *)malloc(shaderLength+1);
if (shaderText != NULL)
{
fread(shaderText, 1, shaderLength, fp);
}
shaderText[shaderLength] = '\0';
fclose(fp);
}
return shaderText;
}
// Compile shaders
void PrepareShader(GLint shaderNum)
{
char fullFileName[255];
GLubyte *fsString;
// Create low-level shader objects and specify shader text
if (lowLevelAvailable)
{
GLint errorPos;
#ifdef __APPLE__
sprintf(fullFileName, "%s.fp", shaderNames[shaderNum]);
#else
sprintf(fullFileName, ".\\shaders\\%s.fp", shaderNames[shaderNum]);
#endif
fsString = LoadShaderText(fullFileName);
if (!fsString)
{
fprintf(stderr, "Unable to load \"%s\"\n", fullFileName);
Sleep(5000);
exit(0);
}
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ids[shaderNum]);
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fsString), fsString);
free(fsString);
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
if (errorPos != -1)
{
fprintf(stderr, "Error in low-level fragment shader #%d at position %d!\n", shaderNum, errorPos);
fprintf(stderr, "Error string: %s\n", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
Sleep(5000);
exit(0);
}
}
// Create high-level shader objects and specify shader text
if (highLevelAvailable)
{
GLcharARB *fsStringPtr[1];
GLint success;
#ifdef __APPLE__
sprintf(fullFileName, "%s.fs", shaderNames[shaderNum]);
#else
sprintf(fullFileName, ".\\shaders\\%s.fs", shaderNames[shaderNum]);
#endif
fsString = LoadShaderText(fullFileName);
if (!fsString)
{
fprintf(stderr, "Unable to load \"%s\"\n", fullFileName);
Sleep(5000);
exit(0);
}
fShader[shaderNum] = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
fsStringPtr[0] = fsString;
glShaderSourceARB(fShader[shaderNum], 1, fsStringPtr, NULL);
free(fsString);
// Compile shaders and check for any errors
glCompileShaderARB(fShader[shaderNum]);
glGetObjectParameterivARB(fShader[shaderNum], GL_OBJECT_COMPILE_STATUS_ARB, &success);
if (!success)
{
GLbyte infoLog[MAX_INFO_LOG_SIZE];
glGetInfoLogARB(fShader[shaderNum], MAX_INFO_LOG_SIZE, NULL, infoLog);
fprintf(stderr, "Error in high-level fragment shader #%d compilation!\n", shaderNum);
fprintf(stderr, "Info log: %s\n", infoLog);
Sleep(10000);
exit(0);
} else
{
GLbyte infoLog[MAX_INFO_LOG_SIZE];
glGetInfoLogARB(fShader[shaderNum], MAX_INFO_LOG_SIZE, NULL, infoLog);
//fprintf(stderr, "High-level fragment shader #%d compile info log: %s\n", shaderNum, infoLog);
}
// Create program object, attach shader, then link
progObj[shaderNum] = glCreateProgramObjectARB();
glAttachObjectARB(progObj[shaderNum], fShader[shaderNum]);
glLinkProgramARB(progObj[shaderNum]);
glGetObjectParameterivARB(progObj[shaderNum], GL_OBJECT_LINK_STATUS_ARB, &success);
if (!success)
{
GLbyte infoLog[MAX_INFO_LOG_SIZE];
glGetInfoLogARB(progObj[shaderNum], MAX_INFO_LOG_SIZE, NULL, infoLog);
fprintf(stderr, "Error in high-level program #%d linkage!\n", shaderNum);
fprintf(stderr, "Info log: %s\n", infoLog);
Sleep(10000);
exit(0);
}
else
{
GLbyte infoLog[MAX_INFO_LOG_SIZE];
glGetInfoLogARB(progObj[shaderNum], MAX_INFO_LOG_SIZE, NULL, infoLog);
//fprintf(stderr, "High-level program #%d link info log: %s\n", shaderNum, infoLog);
}
// Program object has changed, so we should revalidate
needsValidation[shaderNum] = GL_TRUE;
}
}
// Called to draw scene objects
void DrawModels(void)
{
GLTVector3 lightPosEye;
GLTMatrix mv;
// Transform light position to eye space
glPushMatrix();
glRotatef(lightRotation, 0.0, 1.0, 0.0);
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
gltTransformPoint(lightPos, mv, lightPosEye);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glPopMatrix();
// Draw plane that the objects rest on
glColor3f(0.0f, 0.0f, 0.90f); // Blue
glNormal3f(0.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, -25.0f, -100.0f);
glVertex3f(-100.0f, -25.0f, 100.0f);
glVertex3f(100.0f, -25.0f, 100.0f);
glVertex3f(100.0f, -25.0f, -100.0f);
glEnd();
// Draw red cube
glColor3f(1.0f, 0.0f, 0.0f);
glutSolidCube(48.0f);
// Draw green sphere
glColor3f(0.0f, 1.0f, 0.0f);
glPushMatrix();
glTranslatef(-60.0f, 0.0f, 0.0f);
glutSolidSphere(25.0f, 50, 50);
glPopMatrix();
// Draw magenta torus
glColor3f(1.0f, 0.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0f, 0.0f, 60.0f);
glutSolidTorus(8.0f, 16.0f, 50, 50);
glPopMatrix();
// Draw yellow cone
glColor3f(1.0f, 1.0f, 0.0f);
glPushMatrix();
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
glTranslatef(60.0f, 0.0f, -24.0f);
glutSolidCone(25.0f, 50.0f, 50, 50);
glPopMatrix();
// Draw cyan teapot
glColor3f(0.0f, 1.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0f, 0.0f, -60.0f);
glutSolidTeapot(25.0f);
glPopMatrix();
}
// Called to draw scene
void RenderScene(void)
{
GLint pass;
// Track camera angle
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 1.0f, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cameraPos[0], cameraPos[1], cameraPos[2],
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Validate our shader before first use
if (needsValidation[whichShader])
{
GLint success;
glValidateProgramARB(progObj[whichShader]);
glGetObjectParameterivARB(progObj[whichShader], GL_OBJECT_VALIDATE_STATUS_ARB, &success);
if (!success)
{
GLbyte infoLog[MAX_INFO_LOG_SIZE];
glGetInfoLogARB(progObj[whichShader], MAX_INFO_LOG_SIZE, NULL, infoLog);
fprintf(stderr, "Error in program #%d validation!\n", whichShader);
fprintf(stderr, "Info log: %s\n", infoLog);
Sleep(10000);
exit(0);
}
needsValidation[whichShader] = GL_FALSE;
}
// Draw objects in the scene
DrawModels();
// Redraw from texture w/ fragment shader
if (useHighLevel)
{
GLint uniformLoc;
glUseProgramObjectARB(progObj[whichShader]);
uniformLoc = glGetUniformLocationARB(progObj[whichShader], "sampler0");
if (uniformLoc != -1)
{
glUniform1iARB(uniformLoc, 0);
}
uniformLoc = glGetUniformLocationARB(progObj[whichShader], "tc_offset");
if (uniformLoc != -1)
{
glUniform2fvARB(uniformLoc, 9, texCoordOffsets);
}
}
else
{
GLint i;
glEnable(GL_FRAGMENT_PROGRAM_ARB);
for (i = 0; i < 9; i++)
{
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, i, texCoordOffsets[i*2], texCoordOffsets[(i*2)+1], 0.0f, 1.0f);
}
}
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (pass = 0; pass < numPasses; pass++)
{
// Copy original scene to texture
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (windowWidth-textureWidth)/2,
(windowHeight-textureHeight)/2, textureWidth, textureHeight, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glMultiTexCoord2f(GL_TEXTURE0, 0.0f, 0.0f);
glVertex2f(-((GLfloat)textureWidth / (GLfloat)windowWidth), -((GLfloat)textureHeight / (GLfloat)windowHeight));
glMultiTexCoord2f(GL_TEXTURE0, 0.0f, 1.0f);
glVertex2f(-((GLfloat)textureWidth / (GLfloat)windowWidth), ((GLfloat)textureHeight / (GLfloat)windowHeight));
glMultiTexCoord2f(GL_TEXTURE0, 1.0f, 1.0f);
glVertex2f(((GLfloat)textureWidth / (GLfloat)windowWidth), ((GLfloat)textureHeight / (GLfloat)windowHeight));
glMultiTexCoord2f(GL_TEXTURE0, 1.0f, 0.0f);
glVertex2f(((GLfloat)textureWidth / (GLfloat)windowWidth), -((GLfloat)textureHeight / (GLfloat)windowHeight));
glEnd();
}
glEnable(GL_DEPTH_TEST);
if (useHighLevel)
{
glUseProgramObjectARB(0);
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -