]> Pileus Git - grits/blob - examples/tex/tex.c
Use glBlendFuncSeparate for alpha masking in tex.c
[grits] / examples / tex / tex.c
1 /*
2  * Copyright (C) 2009-2010 Andy Spencer <andy753421@gmail.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <gtk/gtk.h>
19 #include <gtk/gtkgl.h>
20 #include <gdk/gdkkeysyms.h>
21 #include <GL/gl.h>
22 #include <GL/glu.h>
23
24 #define crazy_draw(tex) \
25         for (int _i = 0; ({ \
26                 if (_i == 0) { \
27                         /* Clear alpha buffer */ \
28                         glBindTexture(GL_TEXTURE_2D, tex); \
29                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); \
30                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); \
31                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); \
32                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); \
33                         glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_ONE, GL_ZERO); \
34                 } else if (_i == 1) { \
35                         /* Draw pixels */ \
36                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); \
37                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); \
38                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); \
39                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); \
40                         glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ZERO, GL_ZERO); \
41                 } else { \
42                         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); \
43                 } \
44         }), _i < 2; _i++)
45
46 guint tex, texl, texr;
47
48 gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer _)
49 {
50         if (event->keyval == GDK_q)
51                 gtk_main_quit();
52         return FALSE;
53 }
54
55 gboolean on_expose(GtkWidget *drawing, GdkEventExpose *event, gpointer _)
56 {
57         gdouble y = 0;
58
59         /* Setup view */
60         glMatrixMode(GL_PROJECTION);
61         glLoadIdentity();
62         glOrtho(-1,1, -1,1, 10,-10);
63         glMatrixMode(GL_MODELVIEW);
64         glLoadIdentity();
65         glTranslatef(0, 0, -5);
66         glClearColor(0.5, 0.5, 1.0, 1.0);
67         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
68
69         /* Draw white background rectangle */
70         glEnable(GL_COLOR_MATERIAL);
71         glDisable(GL_TEXTURE_2D);
72         glColor3f(1.0, 1.0, 1.0);
73         glBegin(GL_QUADS);
74         glVertex3f(-0.25, -0.75, 0.0);
75         glVertex3f(-0.25,  0.75, 0.0);
76         glVertex3f( 0.25,  0.75, 0.0);
77         glVertex3f( 0.25, -0.75, 0.0);
78         glEnd();
79
80         /* Setup for textures */
81         glEnable(GL_TEXTURE_2D);
82         glEnable(GL_BLEND);
83         glColor4f(1.0, 1.0, 1.0, 1.0);
84         glDisable(GL_COLOR_MATERIAL);
85
86         /* Left */
87         crazy_draw(texl) {
88                 glBegin(GL_QUADS);
89                 glTexCoord2f( 0.0, y);     glVertex3f(-0.75,  0.0, 0.0);
90                 glTexCoord2f( 0.0, 1.0);   glVertex3f(-0.75,  0.5, 0.0);
91                 glTexCoord2f( 2.0, 1.0);   glVertex3f( 0.75,  0.5, 0.0);
92                 glTexCoord2f( 2.0, y);     glVertex3f( 0.75,  0.0, 0.0);
93                 glEnd();
94         }
95
96         /* Right */
97         crazy_draw(texr) {
98                 glBegin(GL_QUADS);
99                 glTexCoord2f(-1.0, y);     glVertex3f(-0.75, 0.0, 0.0);
100                 glTexCoord2f(-1.0, 1.0);   glVertex3f(-0.75, 0.5, 0.0);
101                 glTexCoord2f( 1.0, 1.0);   glVertex3f( 0.75, 0.5, 0.0);
102                 glTexCoord2f( 1.0, y);     glVertex3f( 0.75, 0.0, 0.0);
103                 glEnd();
104         }
105
106         /* Bottom */
107         glBindTexture(GL_TEXTURE_2D, tex);
108         glBegin(GL_QUADS);
109         glTexCoord2f( 0.0, 0.0);   glVertex3f(-0.75, -0.5, 0.0);
110         glTexCoord2f( 0.0, 1.0-y); glVertex3f(-0.75, -0.0, 0.0);
111         glTexCoord2f( 1.0, 1.0-y); glVertex3f( 0.75, -0.0, 0.0);
112         glTexCoord2f( 1.0, 0.0);   glVertex3f( 0.75, -0.5, 0.0);
113         glEnd();
114
115         /* Flush */
116         GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
117         if (gdk_gl_drawable_is_double_buffered(gldrawable))
118                 gdk_gl_drawable_swap_buffers(gldrawable);
119         else
120                 glFlush();
121         return FALSE;
122 }
123 gboolean on_configure(GtkWidget *drawing, GdkEventConfigure *event, gpointer _)
124 {
125         glViewport(0, 0,
126                 drawing->allocation.width,
127                 drawing->allocation.height);
128         return FALSE;
129 }
130
131 guint load_tex(gchar *filename)
132 {
133         GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
134         guchar    *pixels = gdk_pixbuf_get_pixels(pixbuf);
135         int        width  = gdk_pixbuf_get_width(pixbuf);
136         int        height = gdk_pixbuf_get_height(pixbuf);
137         int        alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
138         guint      tex;
139         glGenTextures(1, &tex);
140         glBindTexture(GL_TEXTURE_2D, tex);
141         glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0,
142                         (alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, pixels);
143         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
144         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
145
146         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
147         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
148         g_object_unref(pixbuf);
149         return tex;
150 }
151
152 int main(int argc, char **argv)
153 {
154         gtk_init(&argc, &argv);
155
156         GtkWidget   *window   = gtk_window_new(GTK_WINDOW_TOPLEVEL);
157         GtkWidget   *drawing  = gtk_drawing_area_new();
158         GdkGLConfig *glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(
159                         GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
160                         GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA));
161         g_signal_connect(window,  "destroy",         G_CALLBACK(gtk_main_quit), NULL);
162         g_signal_connect(window,  "key-press-event", G_CALLBACK(on_key_press),  NULL);
163         g_signal_connect(drawing, "expose-event",    G_CALLBACK(on_expose),     NULL);
164         g_signal_connect(drawing, "configure-event", G_CALLBACK(on_configure),  NULL);
165         gtk_widget_set_gl_capability(drawing, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
166         gtk_container_add(GTK_CONTAINER(window), drawing);
167         gtk_widget_show_all(window);
168
169         /* OpenGL setup */
170         GdkGLContext  *glcontext  = gtk_widget_get_gl_context(GTK_WIDGET(drawing));
171         GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(drawing));
172         gdk_gl_drawable_gl_begin(gldrawable, glcontext);
173
174         /* Load texture */
175         texl = load_tex("texls.png");
176         texr = load_tex("texrs.png");
177         tex  = load_tex("tex.png");
178
179         gtk_main();
180
181         gdk_gl_drawable_gl_end(gldrawable);
182 }