Files
third_party_mesa3d/progs/glsl/convolutions.c

469 lines
11 KiB
C
Raw Normal View History

/**
* Convolution with GLSL.
* Note: uses GL_ARB_shader_objects, GL_ARB_vertex_shader, GL_ARB_fragment_shader,
* not the OpenGL 2.0 shader API.
* Author: Zack Rusin
*/
#define GL_GLEXT_PROTOTYPES
#include "readtex.h"
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
enum Filter {
GAUSSIAN_BLUR,
SHARPEN,
MEAN_REMOVAL,
EMBOSS,
EDGE_DETECT,
NO_FILTER,
LAST
};
#define QUIT LAST
struct BoundingBox {
float minx, miny, minz;
float maxx, maxy, maxz;
};
struct Texture {
GLuint id;
GLfloat x;
GLfloat y;
GLint width;
GLint height;
GLenum format;
};
static const char *textureLocation = "../images/girl2.rgb";
static GLfloat viewRotx = 0.0, viewRoty = 0.0, viewRotz = 0.0;
static struct BoundingBox box;
static struct Texture texture;
static GLuint program;
static GLint menuId;
static enum Filter filter = GAUSSIAN_BLUR;
static void checkError(int line)
{
GLenum err = glGetError();
if (err) {
printf("GL Error %s (0x%x) at line %d\n",
gluErrorString(err), (int) err, line);
}
}
static void loadAndCompileShader(GLuint shader, const char *text)
{
GLint stat;
glShaderSource(shader, 1, (const GLchar **) &text, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
if (!stat) {
GLchar log[1000];
GLsizei len;
glGetShaderInfoLog(shader, 1000, &len, log);
fprintf(stderr, "Problem compiling shader: %s\n", log);
exit(1);
}
else {
printf("Shader compiled OK\n");
}
}
static void readShader(GLuint shader, const char *filename)
{
const int max = 100*1000;
int n;
char *buffer = (char*) malloc(max);
FILE *f = fopen(filename, "r");
if (!f) {
fprintf(stderr, "Unable to open shader file %s\n", filename);
exit(1);
}
n = fread(buffer, 1, max, f);
printf("Read %d bytes from shader file %s\n", n, filename);
if (n > 0) {
buffer[n] = 0;
loadAndCompileShader(shader, buffer);
}
fclose(f);
free(buffer);
}
static void
checkLink(GLuint prog)
{
GLint stat;
glGetProgramiv(prog, GL_LINK_STATUS, &stat);
if (!stat) {
GLchar log[1000];
GLsizei len;
glGetProgramInfoLog(prog, 1000, &len, log);
fprintf(stderr, "Linker error:\n%s\n", log);
}
else {
fprintf(stderr, "Link success!\n");
}
}
static void fillConvolution(GLint *k,
GLfloat *scale,
GLfloat *color)
{
switch(filter) {
case GAUSSIAN_BLUR:
k[0] = 1; k[1] = 2; k[2] = 1;
k[3] = 2; k[4] = 4; k[5] = 2;
k[6] = 1; k[7] = 2; k[8] = 1;
*scale = 1./16.;
break;
case SHARPEN:
k[0] = 0; k[1] = -2; k[2] = 0;
k[3] = -2; k[4] = 11; k[5] = -2;
k[6] = 0; k[7] = -2; k[8] = 0;
*scale = 1./3.;
break;
case MEAN_REMOVAL:
k[0] = -1; k[1] = -1; k[2] = -1;
k[3] = -1; k[4] = 9; k[5] = -1;
k[6] = -1; k[7] = -1; k[8] = -1;
*scale = 1./1.;
break;
case EMBOSS:
k[0] = -1; k[1] = 0; k[2] = -1;
k[3] = 0; k[4] = 4; k[5] = 0;
k[6] = -1; k[7] = 0; k[8] = -1;
*scale = 1./1.;
color[0] = 0.5;
color[1] = 0.5;
color[2] = 0.5;
color[3] = 0.5;
break;
case EDGE_DETECT:
k[0] = 1; k[1] = 1; k[2] = 1;
k[3] = 0; k[4] = 0; k[5] = 0;
k[6] = -1; k[7] = -1; k[8] = -1;
*scale = 1.;
color[0] = 0.5;
color[1] = 0.5;
color[2] = 0.5;
color[3] = 0.5;
break;
case NO_FILTER:
k[0] = 0; k[1] = 0; k[2] = 0;
k[3] = 0; k[4] = 1; k[5] = 0;
k[6] = 0; k[7] = 0; k[8] = 0;
*scale = 1.;
break;
default:
assert(!"Unhandled switch value");
}
}
static void setupConvolution()
{
GLint *kernel = (GLint*)malloc(sizeof(GLint) * 9);
GLfloat scale;
GLfloat *vecKer = (GLfloat*)malloc(sizeof(GLfloat) * 9 * 4);
GLuint loc;
GLuint i;
GLfloat baseColor[4];
baseColor[0] = 0;
baseColor[1] = 0;
baseColor[2] = 0;
baseColor[3] = 0;
fillConvolution(kernel, &scale, baseColor);
/*vector of 4*/
for (i = 0; i < 9; ++i) {
vecKer[i*4 + 0] = kernel[i];
vecKer[i*4 + 1] = kernel[i];
vecKer[i*4 + 2] = kernel[i];
vecKer[i*4 + 3] = kernel[i];
}
loc = glGetUniformLocationARB(program, "KernelValue");
glUniform4fv(loc, 9, vecKer);
loc = glGetUniformLocationARB(program, "ScaleFactor");
glUniform4f(loc, scale, scale, scale, scale);
loc = glGetUniformLocationARB(program, "BaseColor");
glUniform4f(loc, baseColor[0], baseColor[1],
baseColor[2], baseColor[3]);
free(vecKer);
free(kernel);
}
static void createProgram(const char *vertProgFile,
const char *fragProgFile)
{
GLuint fragShader = 0, vertShader = 0;
program = glCreateProgram();
if (vertProgFile) {
vertShader = glCreateShader(GL_VERTEX_SHADER);
readShader(vertShader, vertProgFile);
glAttachShader(program, vertShader);
}
if (fragProgFile) {
fragShader = glCreateShader(GL_FRAGMENT_SHADER);
readShader(fragShader, fragProgFile);
glAttachShader(program, fragShader);
}
glLinkProgram(program);
checkLink(program);
glUseProgram(program);
/*
assert(glIsProgram(program));
assert(glIsShader(fragShader));
assert(glIsShader(vertShader));
*/
checkError(__LINE__);
{/*texture*/
GLuint texLoc = glGetUniformLocationARB(program, "srcTex");
glUniform1iARB(texLoc, 0);
}
{/*setup offsets */
float offsets[] = { 1.0 / texture.width, 1.0 / texture.height,
0.0 , 1.0 / texture.height,
-1.0 / texture.width, 1.0 / texture.height,
1.0 / texture.width, 0.0,
0.0 , 0.0,
-1.0 / texture.width, 0.0,
1.0 / texture.width, -1.0 / texture.height,
0.0 , -1.0 / texture.height,
-1.0 / texture.width, -1.0 / texture.height };
GLuint offsetLoc = glGetUniformLocationARB(program, "Offset");
glUniform2fv(offsetLoc, 9, offsets);
}
setupConvolution();
checkError(__LINE__);
}
static void readTexture(const char *filename)
{
GLubyte *data;
texture.x = 0;
texture.y = 0;
glGenTextures(1, &texture.id);
glBindTexture(GL_TEXTURE_2D, texture.id);
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);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
data = LoadRGBImage(filename, &texture.width, &texture.height,
&texture.format);
if (!data) {
printf("Error: couldn't load texture image '%s'\n", filename);
exit(1);
}
printf("Texture %s (%d x %d)\n",
filename, texture.width, texture.height);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
texture.width, texture.height, 0, texture.format,
GL_UNSIGNED_BYTE, data);
}
static void menuSelected(int entry)
{
switch (entry) {
case QUIT:
exit(0);
break;
default:
filter = (enum Filter)entry;
}
setupConvolution();
glutPostRedisplay();
}
static void menuInit()
{
menuId = glutCreateMenu(menuSelected);
glutAddMenuEntry("Gaussian blur", GAUSSIAN_BLUR);
glutAddMenuEntry("Sharpen", SHARPEN);
glutAddMenuEntry("Mean removal", MEAN_REMOVAL);
glutAddMenuEntry("Emboss", EMBOSS);
glutAddMenuEntry("Edge detect", EDGE_DETECT);
glutAddMenuEntry("None", NO_FILTER);
glutAddMenuEntry("Quit", QUIT);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
static void init()
{
if (!glutExtensionSupported("GL_ARB_shader_objects") ||
!glutExtensionSupported("GL_ARB_vertex_shader") ||
!glutExtensionSupported("GL_ARB_fragment_shader")) {
fprintf(stderr, "Sorry, this program requires GL_ARB_shader_objects, GL_ARB_vertex_shader, and GL_ARB_fragment_shader\n");
exit(1);
}
Merge branch 'gallium-0.1' into gallium-0.2 A first attempt at moving gallium onto a branch directly off master... It will be interesting to see how much work this takes to get running. Have resolved the conflicts semi-arbitarily, not compiled or tested. Conflicts: .gitignore Makefile configs/config.mgw configs/darwin configs/darwin-x86ppc configs/default configs/freebsd-dri configs/linux-dri configs/linux-dri-xcb configs/linux-fbdev configs/linux-static configs/linux-x86-64-static configs/linux-x86-static doxygen/Makefile include/GL/gl.h progs/demos/Makefile progs/demos/descrip.mms progs/demos/texenv.c progs/egl/.gitignore progs/egl/Makefile progs/glsl/.gitignore progs/glsl/Makefile progs/glsl/convolutions.c progs/samples/Makefile.mgw progs/tests/.gitignore progs/trivial/.gitignore progs/trivial/point-param.c progs/trivial/tri.c progs/xdemos/.gitignore progs/xdemos/glthreads.c src/egl/drivers/demo/Makefile src/egl/drivers/dri/Makefile src/egl/main/Makefile src/glu/Makefile src/glu/sgi/Makefile src/glu/sgi/Makefile.mgw src/glut/glx/Makefile.mgw src/glut/os2/WarpWin.cpp src/glut/os2/glut_cindex.cpp src/glut/os2/glut_gamemode.cpp src/glut/os2/glut_win.cpp src/glut/os2/glut_winmisc.cpp src/glut/os2/os2_glx.cpp src/glut/os2/os2_menu.cpp src/glut/os2/os2_winproc.cpp src/glw/Makefile src/glx/x11/dri_glx.c src/glx/x11/glxext.c src/mesa/Makefile src/mesa/Makefile.mgw src/mesa/descrip.mms src/mesa/drivers/beos/Makefile src/mesa/drivers/common/descrip.mms src/mesa/drivers/common/driverfuncs.c src/mesa/drivers/directfb/Makefile src/mesa/drivers/dri/Makefile.template src/mesa/drivers/dri/common/dri_bufmgr.c src/mesa/drivers/dri/common/dri_bufmgr.h src/mesa/drivers/dri/common/dri_util.c src/mesa/drivers/dri/common/extension_helper.h src/mesa/drivers/dri/common/mmio.h src/mesa/drivers/dri/common/utils.c src/mesa/drivers/dri/common/utils.h src/mesa/drivers/dri/glcore/Makefile src/mesa/drivers/dri/i810/i810screen.c src/mesa/drivers/dri/i915/intel_ioctl.c src/mesa/drivers/dri/i915/intel_ioctl.h src/mesa/drivers/dri/i915/intel_screen.c src/mesa/drivers/dri/i915/server/i830_common.h src/mesa/drivers/dri/i915/server/i830_dri.h src/mesa/drivers/dri/i965/intel_screen.c src/mesa/drivers/dri/i965/server/i830_common.h src/mesa/drivers/dri/i965/server/i830_dri.h src/mesa/drivers/dri/mach64/mach64_screen.c src/mesa/drivers/dri/nouveau/nouveau_context.h src/mesa/drivers/dri/nouveau/nouveau_fifo.c src/mesa/drivers/dri/nouveau/nouveau_fifo.h src/mesa/drivers/dri/nouveau/nouveau_screen.c src/mesa/drivers/dri/nouveau/nouveau_screen.h src/mesa/drivers/dri/r128/r128_tex.h src/mesa/drivers/dri/savage/savageioctl.h src/mesa/drivers/fbdev/Makefile src/mesa/drivers/osmesa/Makefile src/mesa/drivers/osmesa/descrip.mms src/mesa/drivers/x11/Makefile src/mesa/drivers/x11/descrip.mms src/mesa/drivers/x11/xm_dd.c src/mesa/glapi/glapi.c src/mesa/glapi/glthread.c src/mesa/main/api_validate.c src/mesa/main/attrib.c src/mesa/main/bufferobj.c src/mesa/main/bufferobj.h src/mesa/main/buffers.c src/mesa/main/config.h src/mesa/main/context.c src/mesa/main/descrip.mms src/mesa/main/drawpix.c src/mesa/main/enums.c src/mesa/main/fbobject.c src/mesa/main/glheader.h src/mesa/main/imports.c src/mesa/main/mipmap.c src/mesa/main/mm.c src/mesa/main/mm.h src/mesa/main/mtypes.h src/mesa/main/points.c src/mesa/main/sources src/mesa/main/state.c src/mesa/main/texcompress_fxt1.c src/mesa/main/texenvprogram.c src/mesa/main/texobj.c src/mesa/main/texstate.c src/mesa/main/texstore.c src/mesa/math/descrip.mms src/mesa/shader/arbprogram.c src/mesa/shader/descrip.mms src/mesa/shader/prog_execute.c src/mesa/shader/prog_statevars.c src/mesa/shader/prog_statevars.h src/mesa/shader/prog_uniform.c src/mesa/shader/program.c src/mesa/shader/program.h src/mesa/shader/shader_api.c src/mesa/shader/slang/descrip.mms src/mesa/shader/slang/library/slang_vertex_builtin_gc.h src/mesa/sources src/mesa/swrast/descrip.mms src/mesa/swrast/s_drawpix.c src/mesa/swrast/s_fragprog.c src/mesa/swrast/s_readpix.c src/mesa/swrast/s_span.c src/mesa/swrast_setup/descrip.mms src/mesa/tnl/descrip.mms src/mesa/tnl/t_context.h src/mesa/tnl/t_vp_build.c src/mesa/tnl/tnl.h src/mesa/vbo/descrip.mms src/mesa/vbo/vbo_context.c src/mesa/vbo/vbo_exec_array.c src/mesa/x86-64/xform4.S src/mesa/x86/rtasm/x86sse.c src/mesa/x86/rtasm/x86sse.h windows/VC6/progs/glut/glut.dsp windows/VC7/mesa/gdi/gdi.vcproj windows/VC7/mesa/glu/glu.vcproj windows/VC7/mesa/mesa.sln windows/VC7/mesa/mesa/mesa.vcproj windows/VC7/mesa/osmesa/osmesa.vcproj windows/VC7/progs/glut/glut.vcproj windows/VC8/mesa/gdi/gdi.vcproj windows/VC8/mesa/glu/glu.vcproj windows/VC8/mesa/mesa.sln windows/VC8/mesa/mesa/mesa.vcproj windows/VC8/progs/glut/glut.vcproj
2008-09-11 16:05:15 +01:00
fprintf(stderr, "GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
fprintf(stderr, "GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
fprintf(stderr, "GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
menuInit();
readTexture(textureLocation);
createProgram("convolution.vert", "convolution.frag");
glEnable(GL_TEXTURE_2D);
glClearColor(1.0, 1.0, 1.0, 1.0);
/*glShadeModel(GL_SMOOTH);*/
glShadeModel(GL_FLAT);
}
static void reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
box.minx = 0;
box.maxx = width;
box.miny = 0;
box.maxy = height;
box.minz = 0;
box.maxz = 1;
glOrtho(box.minx, box.maxx, box.miny, box.maxy, -999999, 999999);
glMatrixMode(GL_MODELVIEW);
}
static void keyPress(unsigned char key, int x, int y)
{
switch(key) {
case 27:
exit(0);
default:
return;
}
glutPostRedisplay();
}
static void
special(int k, int x, int y)
{
switch (k) {
case GLUT_KEY_UP:
viewRotx += 2.0;
break;
case GLUT_KEY_DOWN:
viewRotx -= 2.0;
break;
case GLUT_KEY_LEFT:
viewRoty += 2.0;
break;
case GLUT_KEY_RIGHT:
viewRoty -= 2.0;
break;
default:
return;
}
glutPostRedisplay();
}
static void draw()
{
GLfloat center[2];
GLfloat anchor[2];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
center[0] = box.maxx/2;
center[1] = box.maxy/2;
anchor[0] = center[0] - texture.width/2;
anchor[1] = center[1] - texture.height/2;
glTranslatef(center[0], center[1], 0);
glRotatef(viewRotx, 1.0, 0.0, 0.0);
glRotatef(viewRoty, 0.0, 1.0, 0.0);
glRotatef(viewRotz, 0.0, 0.0, 1.0);
glTranslatef(-center[0], -center[1], 0);
glTranslatef(anchor[0], anchor[1], 0);
glBegin(GL_TRIANGLE_STRIP);
{
glColor3f(1., 0., 0.);
glTexCoord2f(0, 0);
glVertex3f(0, 0, 0);
glColor3f(0., 1., 0.);
glTexCoord2f(0, 1.0);
glVertex3f(0, texture.height, 0);
glColor3f(1., 0., 0.);
glTexCoord2f(1.0, 0);
glVertex3f(texture.width, 0, 0);
glColor3f(0., 1., 0.);
glTexCoord2f(1, 1);
glVertex3f(texture.width, texture.height, 0);
}
glEnd();
glPopMatrix();
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitWindowPosition(0, 0);
glutInitWindowSize(400, 400);
glutInitDisplayMode(GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE);
if (!glutCreateWindow("Image Convolutions")) {
fprintf(stderr, "Couldn't create window!\n");
exit(1);
}
init();
glutReshapeFunc(reshape);
glutKeyboardFunc(keyPress);
glutSpecialFunc(special);
glutDisplayFunc(draw);
glutMainLoop();
return 0;
}